ui_1_starting - chrisgoringe/Comfy-Custom-Node-How-To GitHub Wiki
First steps in extending the UI
Making your node send a message
class MyNode:
IS_OUTPUT = True
...
def the_func(self, input, ...):
return { "ui": {"name":value}, "result" : (the output tuple) }
Only output nodes send a message back to the front end; the message is defined by replacing the usual tuple at the end of your function with a dictionary where the tuple is keyed to result
and a message dictionary is keyed to ui
.
How to register an extension
You'll most likely want to write something like:
import { app } from "../../../scripts/app.js";
app.registerExtension({ // 1
name: "a.unqiue.name.for.this.extension",
async beforeRegisterNodeDef(nodeType, nodeData, app) { // 2
if (node?.comfyClass === "The unique name of my node class on the backend") { // 3
const onExecuted = nodeType.prototype.onExecuted; // 4
nodeType.prototype.onExecuted = function (message) {
onExecuted?.apply(this, arguments); // 5
// do something with the message // 6
}
}
},
}),
Walking through that:
- 1 Using the ComfyUI app.js we're registering an extension by passing a unique name and an async function
- 2 The function name determines when it is called - see below
- 3 beforeRegisterNodeDef is called for every nodeType so check if it's your node
- 4 onExecuted is called when the node finishes executing. If there's already an onExecuted method, save it in the const
- 5 replace onExecuted with your new code; the first line of which calls the one you saved
- 5a the only other useful method to replace is onExecutionStart, which is called without parameters at the start of a run
- 6 message is that dictionary you defined in the python 'ui' return
What method names?
Search in app.js for invokeExtensions
- these are the methods that can be used at 2 to get your code called during the startup process.
Method | Parameters | Called | Returns |
---|---|---|---|
init | None | When the page is loaded, before any nodes or workflow | |
setup | None | At the end of the setup | |
addCustomNodeDefs | defs - the node_info for each type of node | Once before any node types are defined | |
getCustomWidgets | None | Once to generate a list of custom widgets | Custom Widget |
nodeCreated | The ComfyNode object for a node type | Once for each node type as created | |
beforeRegisterNodeDef | The ComfyNode object for a node type, and it's node_data | Once for each node type after created, before registering with LiteGraph | |
registerCustomNodes | None | Once after all custom node types have been added | |
loadedGraphNode | node | for each node when it is loaded | not called async |
How to deploy JavaScript
Add a js
folder to your repository, and in __init__.py
include code along these lines:
WEB_DIRECTORY = "./js"
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
When ComfyUI loads your custom node, the js
directory will be copied to [comfy]/web/extensions/A_UNIQUE_NAME, and all .js
files in it will be sent to the browser and executed when the page is loaded.