Alias Nodes: redefine default settings as new nodes

Hi There,

So over at Erlang-Red I just changed default settings on two core nodes[1] because I am constantly resetting those default settings when using the nodes.

Now here my question: won't be great to have "alias" nodes that look like nodes, that smell like nodes but that aren't nodes. I.e., I would define an alias node and that would be added to the palette just as any other node. All these alias nodes would do is have different default settings of the core nodes.

Something akin to the alias command in any Unix shell.

Ideally, these should be definable from within Node-RED and their definition would not require modifications to the settings.js.

Anyway just an idea...

[1] = Debug dumps the entire message and not msg.payload by default and switch "stops after first match" is now default.

3 Likes

Yes, I like the idea. There are several nodes that I always change the defaults for.

And actually, I think that Node-RED already has the makings of an answer - not necessarily an alias as such.

But the flow library can store a single node with settings. It just isn't necessarily as convenient to add to flows because you have to go through the import process.

So perhaps a way to expose entries in libraries into the palette? So they are only a quick drag away? Even better, that would let you attach whole flows to the palette as well, that would be amazing. :smiley:

I'm sure we are not the only two who change that every time we add a debug node :grinning:

4 Likes

And delete the MSG.topic.

I get a huge dump of msg.topic especially when using MySQL queries

Had a quick playaround and this code will create a new node in the palette but ....

(() => {
    let nodeset = RED.nodes.registry.getNodeSetForType("debug");

    nodeset.id = "node-red/alias-debug"
    nodeset.types = ["alias-debug"]

    RED.nodes.registry.addNodeSet(nodeset)

    let theRealDebug = RED.nodes.registry.getNodeType("debug")
    let obj = JSON.parse(JSON.stringify(RED.nodes.registry.getNodeType("debug")))

    obj.defaults.complete.value = true
    obj.type = "alias-debug"

    obj.label = theRealDebug.label;
    obj.labelStyle = theRealDebug.labelStyle;

    obj.onadd = theRealDebug.onadd;
    obj.oneditprepare = theRealDebug.oneditprepare;
    obj.oneditsave = theRealDebug.oneditsave;
    obj.onpaletteadd = theRealDebug.onpaletteadd;
    obj.onpaletteremove = theRealDebug.onpaletteremove;

    RED.nodes.registry.registerNodeType("alias-debug", obj)
})();

... but dragging the node into the workspace and then wanting to edit gives a blank edit panel. No options but when exporting the node, it has the new default setting. No errors in the console ...

DISCLAIMER: this is not the way to do it, just a quick test to add a node to the palette sidebar.

As your node type doesn’t have a corresponding html file I would think :thinking:

ah yer, because the template name gets matched to the type .... of course.

But I don't really want to be defining a new type anyway because I want it to keep the type but have different settings ... hm. :-/

never the less, a working version:

((newType) => {
    let nodeset = RED.nodes.registry.getNodeSetForType("debug");

    nodeset.id = "node-red/" + newType
    nodeset.types = [newType]

    RED.nodes.registry.addNodeSet(nodeset)

    let theRealDebug = RED.nodes.registry.getNodeType("debug")
    let obj = JSON.parse(JSON.stringify(RED.nodes.registry.getNodeType("debug")))

    obj.defaults.complete.value = true
    obj.type = newType;

    obj.label = theRealDebug.label;
    obj.labelStyle = theRealDebug.labelStyle;

    obj.onadd = theRealDebug.onadd;
    obj.oneditprepare = theRealDebug.oneditprepare;
    obj.oneditsave = theRealDebug.oneditsave;
    obj.onpaletteadd = undefined;
    obj.onpaletteremove = undefined;

    let origHtml = $($('script').filter((d, e) => $(e).data('template-name') == "debug")[0]);
    let newElement = origHtml.clone()

    $(newElement).attr("data-template-name", newType)

    origHtml.after(newElement)
    
    RED.nodes.registry.registerNodeType(newType, obj)
})("debug4");

Again a) don't do this at home b) this isn't what I want because a new type is defined but otherwise it's ok :wink:

This is why I said that aligning to the library would be better than trying to mess directly with the nodes. Try adding a debug node to your flow, changing the settings then exporting to the library. Then import it a couple of times.

All that would be required would be something that could add a library entry to the palette and something to handle the drag/drop onto the Editor. This would not only give you custom node settings but entire flows, all from the existing library capability - that custom nodes can also add to themselves!

An "Add to palette" button in the library would give a small dialog to set the colour, name and palette category with done and cancel buttons.

1 Like

One would not want to lose the auto-naming feature of debug nodes.

That happens because the default value for name is ‘_DEFAULT_’ - you do that with any node

OK, but if I export a debug node to the library and then import it again it does not get a new number, even if it has an empty name.

If you set the name to "_DEFAULT_" before export, it will import with a new number.

Doh, I thought I had tried that, but missed the underbars. Thanks.

1 Like

Sorry no you can't: it's done in the onadd function and that is only defined on a limit set of nodes.

Speaking of onadd, using that, it is actually possible to change the type of the added node:

((newType) => {
    let nodeset = RED.nodes.registry.getNodeSetForType("debug");

    nodeset.id = "node-red/" + newType
    nodeset.types = [newType]

    RED.nodes.registry.addNodeSet(nodeset)

    let theRealDebug = RED.nodes.registry.getNodeType("debug")
    let obj = JSON.parse(JSON.stringify(RED.nodes.registry.getNodeType("debug")))

    // new default value
    obj.defaults.complete.value = true

    obj.type = newType;

    obj.label = theRealDebug.label;
    obj.labelStyle = theRealDebug.labelStyle;

    obj.onadd = function() { 
        // revert the node type on add
        this.type = 'debug'; 
        // respect  the _DEFAULT_ name if set
        theRealDebug.onadd.call(this); 
    }

    obj.oneditprepare = theRealDebug.oneditprepare;
    obj.oneditsave = theRealDebug.oneditsave;
    obj.onpaletteadd = undefined;
    obj.onpaletteremove = undefined;

    RED.nodes.registry.registerNodeType(newType, obj)
})("debug-all");

I continue to call the onadd of the original debug node so that _DEFAULT_ is respected for the alias node.

That bit of code is what I was looking for: it will add a node to the palette with the desired defaults and once dragged onto the workspace, it will change its type and the edit panel will also work. It can be saved and will turn up with the type "debug".

I've created a flow to demonstrate this and the flow can be tested directly in the headless NR.

EDIT: Don't do this at home - no warranty given.

EDIT2: This alias node is very ephemeral: it will disappear if you restart, reload or reboot Node-RED. Then you'll have to rerun this flow.