Sanity check: Data differences for 3 types of node addition event

Hi all, I need to be able to differentiate between the different reasons that the nodes:add event is triggered.

I can currently see 4 different reasons:

  1. On initial load of the Editor.
  2. When adding a node to a flow.
  3. When pasting a copied node to a flow.
  4. When importing a node to a flow.

#1 is a real pain because it stops me easily understanding when a node has REALLY been added that wasn't there before.

I need to be able to validate that a setting on a node is not a duplicate of any of the other nodes of the same type and since that requires an API lookup, I want to make sure I'm not doing that when I don't need to. There may also be some differences between the other types of addition and how I need to process them.

So I have gone through and done a data check of the node definition whenever the nodes:add event is triggered. I've come up with the following table of differences but I'd be grateful if a core dev (or anyone else of course) could just validate it.

Load    - `changed`=false, `moved`=❌,  `_config`=✔️,  `l`=❌
New     - `changed`=true,  `moved`=true, `_config`=❌, `l`=true
Paste   - `changed`=true,  `moved`=true, `_config`=✔️,  `l`=❌
Import  - `changed`=true,  `moved`=true, `_config`=✔️,  `l`=❌, _detachFromGroup=false

✔️ - property is present
❌ - property is absent

This might also be useful to other people creating custom nodes.

After some more testing:

Load    - `changed`=false, `moved`=❌,     `_config`=✔️, `l`=❌
New     - `changed`=true,  `moved`=true,    `_config`=❌, `l`=true/❌
Paste   - `changed`=true,  `moved`=true/❌, `_config`=✔️, `l`=❌
Import  - `changed`=true,  `moved`=true/❌, `_config`=✔️,  `l`=❌, _detachFromGroup=false

✔️ - property is present
❌ - property is absent

So I'm using the following tests:

// `node` is the data passed into the 'nodes:add' event.
let addType
if (node.changed === false && !('moved' in node)) addType = 'load'
else if (!('_config' in node)) addType = 'new'
else if (node.changed === true && ('_config' in node)) addType = 'paste/import'

Shame that there does not appear to be a way to differentiate between a copy/paste and an import. However, that is probably OK for my current use.


Also a word of caution

nodes:add fires when you paste a copied node. HOWEVER, you can still press escape at that point which will cancel the paste, remove the pasted node. Similarly after paste and click, you can still undo.

So if you really want to track what nodes are truly added, you also have to track the nodes:remove event which fires if you cancel/undo.

1 Like

Where are you defining the listener's here? node.on("add") was never firing for me

I'm trying to inject some behaviour at the point a node is dropped from the Palette and into the canvas (before a deploy)

I was defining them in the outer section of a node's Editor javascript.

But when I finally twigged that some clever person had added a feature a while back to allow node-specific resources to be loaded in the Editor simply by creating a /resources/ folder in the root of your package, I've now not only moved the editor JS to an external resource file that the node's html loads as a link, but I've also moved some Editor processing that is common across several nodes into a separate file as well.

image

Where ti-common.js contains, amongst other common code, the event handlers:

Note that the code is inside an IIFE (which may be overkill but of course this IS loaded along side many other scripts by the Editor so better safe than sorry) and I make sure that it will only run once no matter how many references to it there are.

Works very well.

The source for the html file (a build step is used to merge in the help and panel html so it is easier to develop.

<link type="text/css" rel="stylesheet" href="./resources/node-red-contrib-uibuilder/ti-common.css" media="all">
<script src="./resources/node-red-contrib-uibuilder/ti-common.js"></script>
<script src="./resources/node-red-contrib-uibuilder/uibuilder.js"></script>

<script type="text/html" class="ti-edit-panel" data-template-name="uibuilder">
<!--=include panel.html -->
</script>

<script type="text/html" data-help-name="uibuilder">
<!--=include help.html -->
</script>

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