mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-28 02:02:08 +00:00
fix: Show title, inputs, and outputs on Vue node component even when node fails to initalize (e.g., if missing) (#5540)
* add missing node error border * update vue node data after configure * [refactor] extract node type resolution to named const - addresses @DrJKL's readability concern Extracted the multi-fallback type resolution logic into a clearly named variable for improved readability and maintainability. * [refactor] convert watch to computed pattern - addresses @DrJKL's structure comment Replaced ref + watch pattern with computed for displayTitle, providing cleaner reactive behavior and eliminating the need for manual sync logic.
This commit is contained in:
@@ -202,10 +202,17 @@ export const useGraphNodeManager = (graph: LGraph): GraphNodeManager => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const nodeType =
|
||||||
|
node.type ||
|
||||||
|
node.constructor?.comfyClass ||
|
||||||
|
node.constructor?.title ||
|
||||||
|
node.constructor?.name ||
|
||||||
|
'Unknown'
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: String(node.id),
|
id: String(node.id),
|
||||||
title: node.title || 'Untitled',
|
title: typeof node.title === 'string' ? node.title : '',
|
||||||
type: node.type || 'Unknown',
|
type: nodeType,
|
||||||
mode: node.mode || 0,
|
mode: node.mode || 0,
|
||||||
selected: node.selected || false,
|
selected: node.selected || false,
|
||||||
executing: false, // Will be updated separately based on execution state
|
executing: false, // Will be updated separately based on execution state
|
||||||
@@ -612,7 +619,7 @@ export const useGraphNodeManager = (graph: LGraph): GraphNodeManager => {
|
|||||||
// Set up widget callbacks BEFORE extracting data (critical order)
|
// Set up widget callbacks BEFORE extracting data (critical order)
|
||||||
setupNodeWidgetCallbacks(node)
|
setupNodeWidgetCallbacks(node)
|
||||||
|
|
||||||
// Extract safe data for Vue
|
// Extract initial data for Vue (may be incomplete during graph configure)
|
||||||
vueNodeData.set(id, extractVueNodeData(node))
|
vueNodeData.set(id, extractVueNodeData(node))
|
||||||
|
|
||||||
// Set up reactive tracking state
|
// Set up reactive tracking state
|
||||||
@@ -657,7 +664,11 @@ export const useGraphNodeManager = (graph: LGraph): GraphNodeManager => {
|
|||||||
// Chain our callback with any existing onAfterGraphConfigured callback
|
// Chain our callback with any existing onAfterGraphConfigured callback
|
||||||
node.onAfterGraphConfigured = useChainCallback(
|
node.onAfterGraphConfigured = useChainCallback(
|
||||||
node.onAfterGraphConfigured,
|
node.onAfterGraphConfigured,
|
||||||
initializeVueNodeLayout
|
() => {
|
||||||
|
// Re-extract data now that configure() has populated title/slots/widgets/etc.
|
||||||
|
vueNodeData.set(id, extractVueNodeData(node))
|
||||||
|
initializeVueNodeLayout()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// Not during workflow loading - initialize layout immediately
|
// Not during workflow loading - initialize layout immediately
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onErrorCaptured, ref, watch } from 'vue'
|
import { computed, onErrorCaptured, ref } from 'vue'
|
||||||
|
|
||||||
import EditableText from '@/components/common/EditableText.vue'
|
import EditableText from '@/components/common/EditableText.vue'
|
||||||
import type { VueNodeData } from '@/composables/graph/useGraphNodeManager'
|
import type { VueNodeData } from '@/composables/graph/useGraphNodeManager'
|
||||||
@@ -74,18 +74,18 @@ const isEditing = ref(false)
|
|||||||
|
|
||||||
const nodeInfo = computed(() => props.nodeData || props.node)
|
const nodeInfo = computed(() => props.nodeData || props.node)
|
||||||
|
|
||||||
// Local state for title to provide immediate feedback
|
const EMPTY_STRING = ''
|
||||||
const displayTitle = ref(nodeInfo.value?.title || 'Untitled')
|
const DEFAULT_TITLE = 'Untitled'
|
||||||
|
|
||||||
// Watch for external changes to the node title
|
const resolveTitle = (info: LGraphNode | VueNodeData | undefined) => {
|
||||||
watch(
|
const title = (info?.title ?? EMPTY_STRING).trim()
|
||||||
() => nodeInfo.value?.title,
|
if (title.length > 0) return title
|
||||||
(newTitle) => {
|
const type = (info?.type ?? EMPTY_STRING).trim()
|
||||||
if (newTitle && newTitle !== displayTitle.value) {
|
return type.length > 0 ? type : DEFAULT_TITLE
|
||||||
displayTitle.value = newTitle
|
}
|
||||||
}
|
|
||||||
}
|
// Computed title that provides reactive updates
|
||||||
)
|
const displayTitle = computed(() => resolveTitle(nodeInfo.value))
|
||||||
|
|
||||||
// Event handlers
|
// Event handlers
|
||||||
const handleCollapse = () => {
|
const handleCollapse = () => {
|
||||||
@@ -109,7 +109,5 @@ const handleTitleEdit = (newTitle: string) => {
|
|||||||
|
|
||||||
const handleTitleCancel = () => {
|
const handleTitleCancel = () => {
|
||||||
isEditing.value = false
|
isEditing.value = false
|
||||||
// Reset displayTitle to the current node title
|
|
||||||
displayTitle.value = nodeInfo.value?.title || 'Untitled'
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user