Inherit config to all custom nodes

Hi everybody,

I'm creating an integration with multiple nodes. Each of these need a configuration node type and other html configs like checkbox etc. How can I embed the necessary html and script parts in each html file without replicating the code in all nodes...

Thanks in advance!

Marco

Not 100% certain what you mean. a config node (like the ones using in MQTT nodes) are setup once and re-used on each MQTT node that uses them.

If you mean your regular nodes have similar HTML options, then you have to add them to each node.

You could programmatically build the edit form using an imported script. but you would need to handle the oneditprepare and the oneditsave to load and extract the values.

Yes, the latter. Thanks I will add them manually

For the Editor HTML, you can load a resource file for common JS and CSS. You can load HTML dynamically as well. There is an example in the uib-element node for UIBUILDER where a 2nd tab of advanced settings may need to be different for each element type. I use a single node config variable that is an object to give me a standard config variable to work with no matter what data the optional tab might record from the admin user.

For the runtime, you can use a simple node.js module. You require the module in each runtime js but node.js is clever enough to only load it once and simply re-uses it. In UIBUILDER, most of my reusable code is contained in such library modules and I use classes but export the class instance not the class so that I am only ever using 1 instance. You don't have to use classes but I find them more logical to work with than JavaScripts prototype model. JS classes use prototypes under the skin but using classes hides the weirdness. This is especially useful as we are about to move to node.js v18 as a baseline for Node-RED because we now finally have access to private methods as well as private variables.

Thanks!

You mean those?

Will have a look, but is a lot of very good code :sweat_smile: .... will try to wrap my head around

1 Like

I'd forgotten how I did things! Been a while. Check out:

That folder is where the html snippets for uib-elements edit panel tabs go. This all changes quite heavily in v7 (in development), but in the v6 series, the html files for each node are built on the fly by a gulp watch script from a series of source files. Made it a lot easier to edit the various parts of the html file which gets horridly complex for large nodes. You will see that each of the files is an HTML snippet that is bundled into the main html file.

This code handles the display of the correct snippet:

(currently mostly commented out since I don't have any additional settings for any of the element types at present)

You can see the default loaded snippet here:

It is loaded into a template tag which makes it very easy to manage dynamically and is never part of the DOM until you clone its contents to somewhere.

Not sure that is absolutely the best way to do it though, there are other possibilities. Such as dynamically loading snippets as I do in my router front-end library. But it works well enough for small-ish amounts of html.

Hi,

tried to do something ugly.

this is my html file for the node:

<script src="resources/node-red-contrib-c8y/configheader.js"></script>
<script type="text/javascript">
    RED.nodes.registerType('call-endpoint',{
        category: 'Cumulocity',
        color: '#a6bbcf',
        defaults: {
            name: {value:""},
            c8yconfig: {value:"", type:"c8yconfig"},
            useenv: {value: false},
            method: {value:"GET"},
            endpoint: {value: ''},

        },
        inputs:1,
        outputs:1,
        icon: "file.png",
        label: function() {
            return this.name||"call-endpoint";
        },
        oneditprepare: function() {
 
            $("#node-input-name").parent().append($(getHeader()));
            $('#node-input-useenv').change(function() {
                if ($(this).is(':checked')) {
                    $('#c8yconfig-row').hide();
                } else {
                    $('#c8yconfig-row').show();
                }
            });
        }
    });
</script>

<script type="text/html" data-template-name="call-endpoint" id="config-form">
    <div class="form-row" id="test">
        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
        <input type="text" id="node-input-name" placeholder="Name">
    </div>
    <div class="form-row">
        <label for="node-input-endpoint"><i class="fa fa-tag"></i> Endpoint</label>
        <input type="text" id="node-input-endpoint" placeholder="e.g. /service/where-am-i/findMe">
    </div>
    <div class="form-row">
        <label for="node-input-method"><i class="fa fa-tag"></i> Method</label>
        <input type="text" id="node-input-method" placeholder="e.g. GET">
    </div>
</script>

<script type="text/html" data-help-name="call-endpoint">
    <p>A node that calls a specified Cumulocity endpoint.</p>
</script>

I tried

 oneditprepare: function() {
 
            $("#node-input-name").parent().append($(getHeader()));
}

where getHeader supplies the additional html.

function getHeader() {

  return `<div class="form-row">
            <label for="node-input-useenv"><i class="fa fa-tag"></i> Use ENV</label>
            <input type="checkbox" id="node-input-useenv"/>
          </div>
          <div class="form-row" id="c8yconfig-row">
              <label for="node-input-c8yconfig"><i class="fa fa-tag"></i> C8y config</label>
              <input type="text" id="node-input-c8yconfig" placeholder="c8yconfig">
          </div>`;
}

seems to work for text input but not for the config node. My issue is that I could not find out which method is actually rendering the data-template
I assume there must be some hook that I'm missing.....

Thanks and sorry for my lack of understanding.

Kind Regards,

Marco

Node-RED does that for you. You don't get to see the mechanics of it. Not forgetting that NR has to juggle many different node modules.

Hmm. I think it should work though I don't use config nodes in my own nodes at present.

You might want to try and wade through this node's code though, I can see that they are doing a fair bit of dynamic stuff:

Maybe that will help?