Proper way to define & namespace functions in a node

When writing client side static JS functions, what is the proper way to define and then call them so they are specific to the node I am creating?

Are we supposed to declare functions within the registerType call? If so, how do you call the function?

 RED.nodes.registerType(‘my-custom-node’,{
	oneditprepare: function(){
		console.log("prepare this node");
		renderTable('table-container-id'); // <- where to define and how to call my own function?
	},
	renderTable: function(tableContainerId){
		// render a table
	}
}

Further, how would I re-use renderTable in all of my package's nodes?

if I define my function outside the registerType call, I end up with a global function which could obviously create a collision.

2 Likes

If all of your nodes are defined in the same file, then you can wrap all of your code in a self-executing function to keep the scope private to the file:

(function() {

   function renderTable(tableContainerId) { ... }
   
   RED.nodes.registerType("node-one", {....})

   RED.nodes.registerType("node-two", {....})

})();

In other words, everything inside that enclosing function can see renderTable, but nothing outside of it can.

If you nodes are split across multiple files, it gets a bit more involved.

Previously, we've suggested putting them in your own separate .js file and then use a custom admin end point to serve up the file and a <script> tag in your node's html to load it in. That has never been an entirely satisfactory answer as it involves too many pieces for what ought to be a relatively straight forward task. Plus it is still loading the code into the global namespace.

Another option that I hadn't considered before is what you propose in your question - essentially adding the function to one of your node's type definitions. You can then access that from anywhere else with:

RED.nodes.getType("my-custom-node").renderTable("xyz");

I can't immediately see why that wouldn't work.

The final option is, as you say, just declare a global function that is visible to everything and pick a name that is unlikely to cause a clash - for example, prefix it with your node-type in some format.

4 Likes

You could use an IFFE and create your own namespace in a function.

(function () { /* ... */ })();

EDIT: Okay... what Nick said, he was faster and has a better example. :grin:

Depending on the need, another possibility would be an API so that the core node definition carries the processing.


Would that appear in the pallet?

I'm trying the getType approach. I'm defining all of my functions under my highest level config node and then setting a reference to it with getType anywhere I need to use those functions.

Why would the pallet be affected?

I can't remember what defines an entry in the pallet. Is it the .html file or the .js file or a combination of those and the package.json entry?

I can't remember what defines an entry in the pallet. Is it the .html file or the .js file or a combination of those and the package.json entry?

I'm just adding new properties to the node's registration. Those properties aren't used by NR to render the node, so the pallet shouldn't be affected. But those properties are accessible from any other node's HTML file by using the getType method, so it makes for a convenient place to define and namespace all of my functions.

Drat! There is just too much complexity to track in JavaScript for an amateur programmer!

... hunts for VScode to make sensible changes to uibuilder that he'd never thought about!! ...

1 Like

Some of the options in the registerType function impact the pallet - like I said, I can't remember what impact that might have. I assume none since you aren't likely to set them but I don't know for sure which is why I asked Nick.

Yeah, there are definitely "reserved" properties... I think this is the list

BTW, looks like you just need the category entry for your node to turn up in the palette.

For anyone coming across this who is looking for an example:

Here I'm adding a method to my node's type definition

And then I'm calling it over here.

2 Likes