# Limiting config node to one instance

**URL:** <https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244>\
**Category:** Developing Nodes\
**Created:** [8 October 2024 17:53 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244 "2024-10-08T17:53:31Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![jpadie](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jpadie/32/87036_2.png) [@jpadie](https://discourse.nodered.org/u/jpadie)\
**Post date:** [8 October 2024 17:53 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/1 "2024-10-08T17:53:31Z")

</div>

is there a method to ensure that the editor is limited to only one config node of a type? The specific use case sets up a listener on a specific port so creating more than one instance of the config node makes little sense.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [8 October 2024 17:57 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/2 "2024-10-08T17:57:51Z")

</div>

It is not

the user can create any number of instances of your node as they wish.  
you will need to manage this your self, and design the config node to handle such a situation.

---

<div class="post-metadata">

**Author:** ![jpadie](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jpadie/32/87036_2.png) [@jpadie](https://discourse.nodered.org/u/jpadie)\
**Post date:** [8 October 2024 18:45 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/3 "2024-10-08T18:45:11Z")

</div>

thank you Marcus.

Do you or others have advice on how to manage that process within the custom code? It would seem that somehow, to protect the user from herself/himself, I need to find a way of getting all the nodes of a certain type and ensuring they return the equivalent of a singleton. is there an API call to return those nodes?

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [8 October 2024 18:59 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/4 "2024-10-08T18:59:56Z")

</div>

Hi @jpadie

In your config Node UI logic.  
You can fetch already deployed “config” nodes.

And if a config node exists with the same type…. Scream at the user to not deploy the one that is moments away of being deployed

`RED.nodes.eachConfig((c) => {})`

I am using my phone currently, but each config returned will have its type (and everything else)

So if your config type is in the loop, they have already deployed a config of your type

**EDIT**  
No longer using my phone.

```auto
/* oneditprepare maybe? */
RED.nodes.eachConfig((c) => {
    if (c.type === 'your-config-type') {
        alert(`Ehhh! you have one already (${c.name}), you sure you know what you're doing`)
    }
});

```

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [8 October 2024 19:36 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/5 "2024-10-08T19:36:53Z")

</div>

Yep, it's possible with:

```js
onadd: function() {
  let hasConfig = false
  RED.nodes.eachConfig(function (n) {
    if (n.id === 'some-fixed-id')
      hasConfig = true
    });

  if ( !hasConfig ) {
    var configNode = {
      id: "some-fixed-id",
      _def: RED.nodes.getType("your-config-node-type"),
      type: "your-config-node-type",
      users: []
    };
    RED.nodes.add(configNode);
    RED.nodes.dirty(true);
  }
}

```

Basically when the user adds the node, this function will check if the node exists and if not create it. You don't have to create a selection input.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [8 October 2024 19:56 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/6 "2024-10-08T19:56:38Z")

</div>

> [@jpadie](#):
>
> Do you or others have advice on how to manage that process within the custom code?

If you check out some of the code in the uibuilder node, you will see that it has checks to ensure that the URL setting is unique across all instances. This may give you some clues as to how to approach it. The relevant code lives in a common library:

> <https://github.com/TotallyInformation/node-red-contrib-uibuilder/blob/main/resources/ti-common.js>

That at least lets you disable the "Done" button and lets you display a warning to users.

---

<div class="post-metadata">

**Author:** ![jpadie](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jpadie/32/87036_2.png) [@jpadie](https://discourse.nodered.org/u/jpadie)\
**Post date:** [10 October 2024 17:28 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/7 "2024-10-10T17:28:40Z")

</div>

Thank you all who responded.

I like the look of the silently added config but (@GogoVega ) I am unfamiliar with the onadd method and where its hook is. Is there any documentation to describe its use?

thank you  
Justin

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [10 October 2024 17:47 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/8 "2024-10-10T17:47:54Z")

</div>

Woops sorry it's a editor property like `oneditprepare`.

It's not documented but is part of:  
[https://nodered.org/docs/creating-nodes/node-html](https://nodered.org/docs/creating-nodes/node-html)

---

<div class="post-metadata">

**Author:** ![jpadie](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jpadie/32/87036_2.png) [@jpadie](https://discourse.nodered.org/u/jpadie)\
**Post date:** [10 October 2024 18:46 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/9 "2024-10-10T18:46:29Z")

</div>

thank you @GogoVega

is it a synonym for onpaletteadd?

testing at this end onadd does not appear to be called when adding a node _from_ the palette to the editor. nor on deploy.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [10 October 2024 18:54 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/10 "2024-10-10T18:54:29Z")

</div>

`oneditprepare`  
Executed before a node (in the flow) is opened up for editing.

`onpaletteadd`  
Executed when your node is indexed, and available to be used from the palette.

So you want to attach to `onpaletteadd` to create a config, which is triggered AFTER your node is installed.

I think that is approach one should take.  
I don't use `onpaletteadd` so could be wrong

- `category`: (string) the palette category the node appears in
- `defaults`: (object) the [editable properties](https://nodered.org/docs/creating-nodes/properties) for the node.
- `credentials`: (object) the [credential properties](https://nodered.org/docs/creating-nodes/credentials) for the node.
- `inputs`: (number) how many inputs the node has, either `0` or `1`.
- `outputs`: (number) how many outputs the node has. Can be `0` or more.
- `color`: (string) the [background colour](https://nodered.org/docs/creating-nodes/appearance#background-colour) to use.
- `paletteLabel`: (string|function) the [label](https://nodered.org/docs/creating-nodes/appearance#label) to use in the palette.
- `label`: (string|function) the [label](https://nodered.org/docs/creating-nodes/appearance#label) to use in the workspace.
- `labelStyle`: (string|function) the [style](https://nodered.org/docs/creating-nodes/appearance#label-style) to apply to the label.
- `inputLabels`: (string|function) optional [label](https://nodered.org/docs/creating-nodes/appearance#port-labels) to add on hover to the input port of a node.
- `outputLabels`: (string|function) optional [labels](https://nodered.org/docs/creating-nodes/appearance#port-labels) to add on hover to the output ports of a node.
- `icon`: (string) the [icon](https://nodered.org/docs/creating-nodes/appearance#icon) to use.
- `align`: (string) the [alignment](https://nodered.org/docs/creating-nodes/appearance#alignment) of the icon and label.
- `button`: (object) adds a [button](https://nodered.org/docs/creating-nodes/appearance#buttons) to the edge of the node.
- `oneditprepare`: (function) called when the edit dialog is being built. See [custom edit behaviour](https://nodered.org/docs/creating-nodes/properties#custom-edit-behaviour).
- `oneditsave`: (function) called when the edit dialog is okayed. See [custom edit behaviour](https://nodered.org/docs/creating-nodes/properties#custom-edit-behaviour).
- `oneditcancel`: (function) called when the edit dialog is canceled. See [custom edit behaviour](https://nodered.org/docs/creating-nodes/properties#custom-edit-behaviour).
- `oneditdelete`: (function) called when the delete button in a configuration node’s edit dialog is pressed. See [custom edit behaviour](https://nodered.org/docs/creating-nodes/properties#custom-edit-behaviour).
- `oneditresize`: (function) called when the edit dialog is resized. See [custom edit behaviour](https://nodered.org/docs/creating-nodes/properties#custom-edit-behaviour).  
👇
- `onpaletteadd`: (function) called when the node type is added to the palette.  
☝
- `onpaletteremove`: (function) called when the node type is removed from the palette.

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [10 October 2024 19:18 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/11 "2024-10-10T19:18:18Z")

</div>

If I remember correctly, it's triggered when the user dragged a node onto the workspace from the palette.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [10 October 2024 20:13 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/12 "2024-10-10T20:13:42Z")

</div>

From my notes:

```auto
/** Available methods:
 * onadd: (function) Called when added to a flow (drag from palette, copy/paste, import) - WARN: If paste/import cancelled this is still fired.
 * oneditprepare: (function) called when the edit dialog is being built.
 * oneditsave: (function) called when the edit Done button pressed - before save happens.
 * oneditcancel: (function) called when the edit Cancel button pressed - before cancel happens.
 * oneditdelete: (function) called when the delete button in a configuration node’s edit dialog is pressed - before delete.
 * oneditresize: (function) called when the edit dialog is resized.
 * onpaletteadd: (function) called when the node type is added to the palette.
 * onpaletteremove: (function) called when the node type is removed from the palette.
 */

```

I maintain a node-red-testbed repo where I do my experiments, you can see it on GitHub. Very useful when trying to work things like this out.

---

<div class="post-metadata">

**Author:** ![jpadie](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jpadie/32/87036_2.png) [@jpadie](https://discourse.nodered.org/u/jpadie)\
**Post date:** [17 October 2024 12:09 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/13 "2024-10-17T12:09:21Z")

</div>

Thanks for this list Julian. and thanks all for chiming in above.

Interestingly I am finding that onpaletteadd is fired at every reload of the browser. So the below-posted coderesults in a new config node getting created for every reload of the editor.

I appreciate that literally the node type is being "added" to the palette at every reload however I read the docs as meaning that the function would be run _once_ when the node was added to the palette-set on first installation via the palette manager. I wonder whether others are being misled by this ambiguity?

What's also interesting is that when running onpaletteadd the editor does not appear to have access to the eachConfig method of the RED.nodes api. but it is available after the page has loaded (or at some time before). the screenshot below should show that RED.nodes.eachConfig results in a couple of nodes that should have resulted in hasConfig = true; but in fact nothing is returned so the lambda function is never called.

```auto
onpaletteadd: function () {
            let hasConfig = false;
            RED.notify('palette add being run by hvac');
            console.log("palette add being run by hvac");
            RED.nodes.eachConfig((n) => {
                console.log("inside the each config");
                console.log(n);
                if (n.type === 'matter-hub') hasConfig = true;
                this.serverNode = n.id;
                $("#node-input-serverNode").val(n.id);
            });
            if (!hasConfig) {
                RED.notify('creating config');
                console.log("creating config");
                const configNode = {
                    id: RED.nodes.id(),
                    _def: RED.nodes.getType("matter-hub"),
                    type: "matter-hub",
                    users: []
                };
                RED.nodes.add(configNode);
                RED.nodes.dirty(true);
                this.serverNode = configNode.id;
                $("#node-input-serverNode").val(configNode.id);
            } else {
                RED.notify('not creating config');
            }
        },

```

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/1/7186261a9c62f8f574248e2309f7240b24c87a62.png)

---

<div class="post-metadata">

**Author:** ![jpadie](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jpadie/32/87036_2.png) [@jpadie](https://discourse.nodered.org/u/jpadie)\
**Post date:** [18 October 2024 17:03 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/14 "2024-10-18T17:03:52Z")

</div>

Just flagging that I have worked around the issue for my own needs (by exporting a singleton that is used by the device nodes and wholly avoiding config nodes). The above may be useful for other's coming across confusion over onpaletteadd.

Using onadd would also have been an entirely valid solution as the registry has been fully loaded by then.

---

<div class="post-metadata">

**Author:** ![jpadie](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jpadie/32/87036_2.png) [@jpadie](https://discourse.nodered.org/u/jpadie)\
**Post date:** [18 October 2024 19:59 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/15 "2024-10-18T19:59:39Z")

</div>

@TotallyInformation  
I see there is also an onremove callback that can be used (there's a deprecation warning attached). Fired when the node is deleted from the flow.

and that the oneditdelete event appears to relate to all node types and not just the config node; and is fired when the node is deleted from the flow.

cf @node-red/editor-client/public/red/red.js around lines 5240 - 5257

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [17 December 2024 20:00 UTC](https://discourse.nodered.org/t/limiting-config-node-to-one-instance/92244/16 "2024-12-17T20:00:16Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
