Custom Node Testing
Expected Behavior
Descriptions:
The problem is that when writing a custom extension that adds another widget to the node (for example, my Speech And Recognition extension : https://github.com/AlekPet/ComfyUI_Custom_Nodes_AlekPet/blob/master/ExtrasNode/js/extras_speech_and_recognition.js ), which has a multi-text field and forceInput, it incorrectly loads data from the workflow.
Maybe I somehow incorrectly add the widget to the node, but with two multi-text fields, everything works fine 😄 .
I made a more simplified version of the verification extension, which uses one checkbox and stores its value.
force_input_mtext.mp4
Example python code nodes.
class TestTextNode :
@ classmethod
def INPUT_TYPES (cls ):
return {
"required" : {
"text" : ("STRING" , {"default" : "" , "forceInput" :True }),
"words" : ("STRING" , {"multiline" : True , "default" : "" }),
},
}
RETURN_TYPES = ("STRING" ,)
RETURN_NAMES = ("STRING" ,)
CATEGORY = "alekpet-test"
DESCRIPTION = "This node outputs text."
FUNCTION = "ret_text"
def ret_text (self , text = "" , words = "" ):
result_text = text * 5
return (result_text ,)
class TestTextTwoNode :
@ classmethod
def INPUT_TYPES (cls ):
return {
"required" : {
"text" : ("STRING" , {"default" : "" , "forceInput" :True }),
"words" : ("STRING" , {"multiline" : True , "default" : "" }),
"words2" : ("STRING" , {"multiline" : True , "default" : "" }),
},
}
RETURN_TYPES = ("STRING" ,)
RETURN_NAMES = ("STRING" ,)
CATEGORY = "alekpet-test"
DESCRIPTION = "This node outputs text."
FUNCTION = "ret_text_two"
def ret_text_two (self , text = "" , words = "" , words2 = "" ):
result_text = text * 5
return (result_text ,)
Example js code extension.
import { app } from "../../scripts/app.js" ;
import { $el } from "../../scripts/ui.js" ;
const idExt = "alekpet.hello_world" ;
// -- Extension: Speak text & Recognition speech --
app . registerExtension ( {
name : idExt ,
async beforeRegisterNodeDef ( nodeType , nodeData , app ) {
// Node Created
const onNodeCreated = nodeType . prototype . onNodeCreated ;
nodeType . prototype . onNodeCreated = async function ( ) {
const ret = onNodeCreated
? onNodeCreated . apply ( this , arguments )
: undefined ;
let nodeIsMultiString = false ;
if ( nodeData ?. input && nodeData ?. input ?. required ) {
for ( const inp of Object . keys ( nodeData . input . required ) ) {
if (
nodeData . input . required [ inp ] [ 1 ] ?. multiline &&
! nodeData . input . required [ inp ] [ 1 ] ?. forceInput
) {
const type = nodeData . input . required [ inp ] [ 0 ] ;
if ( [ "STRING" ] . includes ( type ) ) {
nodeIsMultiString = true ;
break ;
}
}
}
}
if ( nodeData ?. output ) {
for ( const out of nodeData . output ) {
const isElementTextArea = this ?. widgets ?. some (
( w ) =>
w ?. element ?. tagName === "TEXTAREA" ||
w ?. inputEl ?. tagName === "TEXTAREA"
) ;
if ( isElementTextArea && [ "STRING" ] . includes ( out ) ) {
nodeIsMultiString = true ;
break ;
}
}
}
if ( ! nodeIsMultiString ) return ret ;
// Find all widget type customtext
const widgetsTextMulti = this ?. widgets ?. filter ( ( w ) =>
[ "customtext" , "converted-widget" ] . includes ( w . type )
) ;
const isIncludesSpeech = this ?. widgets ?. some (
( w ) => w . type === "hello_world_type"
) ;
if ( ! isIncludesSpeech && widgetsTextMulti ?. length ) {
widgetsTextMulti . forEach ( async ( w ) => {
const el = $el ( "input.widget_hello_world_el" , { type : "checkbox" } ) ;
this . addDOMWidget ( "widget_hello_world" , "hello_world_type" , el , {
setValue ( v ) {
el . checked = v ;
} ,
getValue ( ) {
return ! ! el . checked ;
} ,
} ) ;
} ) ;
}
return ret ;
} ;
} ,
} ) ;
Video console.log:
https://github.com/user-attachments/assets/9866e660-82cb-4a87-9f45-4cf1d23f247c
The entire extension and test users can be found here: alek_test.zip
And the workflow for testing: load_data_workflow_forcedinput_one_mtext.json
Actual Behavior
It should load and save normally as with one multi-text field. As with input data that does not have a property in the forceInput field.
Steps to Reproduce
Enable or install an extension that adds a new widget to a multi-text field
Add a widget with forceInput and one multi-text field to the workflow
Change the values in the fields
Switch to another workflow or refresh the page.
See the result of loading values.****
Debug Logs
In the onSerialize method if you track all the values are saved correctly.
this.onSerialize = (o)= > {
console.log(o.type, o.widgets_values)
}
Video console.log below in the Expected Behavior
Other
Perhaps it is necessary to somehow process the data when loading, but why does everything work with two or more multi-text fields, but with one the loading of values breaks, reducing the data in the widgets_values array.
Custom Node Testing
Expected Behavior
Descriptions:
The problem is that when writing a custom extension that adds another widget to the node (for example, my Speech And Recognition extension: https://github.com/AlekPet/ComfyUI_Custom_Nodes_AlekPet/blob/master/ExtrasNode/js/extras_speech_and_recognition.js), which has a multi-text field and forceInput, it incorrectly loads data from the workflow.
Maybe I somehow incorrectly add the widget to the node, but with two multi-text fields, everything works fine 😄 .
I made a more simplified version of the verification extension, which uses one checkbox and stores its value.
force_input_mtext.mp4
Example python code nodes.
Example js code extension.
Video console.log:
https://github.com/user-attachments/assets/9866e660-82cb-4a87-9f45-4cf1d23f247c
The entire extension and test users can be found here: alek_test.zip
And the workflow for testing: load_data_workflow_forcedinput_one_mtext.json
Actual Behavior
It should load and save normally as with one multi-text field. As with input data that does not have a property in the forceInput field.
Steps to Reproduce
Debug Logs
Other
Perhaps it is necessary to somehow process the data when loading, but why does everything work with two or more multi-text fields, but with one the loading of values breaks, reducing the data in the widgets_values array.