ok, so firstly, as I said before...
I even went to the effort to provide an example of how to handle that...
... but you have ignore it and stayed with generating objects with a fixed ID.
never mind!
A solution, take it or leave it...
NOTE: I dont know what is inside data
but I can see there is at least a .name
and a .address
property so i will use them in my example.
STEPS...
- Add a property for storing client side values [client side HTML] Firstly, you need somewhere for the values to be stored (at the HTML side). Add a property to the defaults. At the beginning of the HTML node script, you will have something like the below script. Add a property called
dynamicOptions
.
NOTE: this is essential if you want to get your values into the server side JS
RED.nodes.registerType('mynode', {
category: "input",
icon: "timer.png",
color: "#a6bbcf",
inputs: 1,
outputs: 1,
defaults: {
name: { value: "" },
dynamicOptions: { value: [] }, //<< Add property to hold users node settings
},
...,
- Setup the dynamic elements [client side HTML] Next, you need to setup the dynamic DOM elements so that you can pick up the
data
values and checkbox state (when the user presses the "Done" button after editing)
// At the beginning of your oneditprepare() function...
const parentDiv = $("#dialog-form"); // <<make sure this selects YOUR nodes DIV
var inputNo = 1;
// later on in your oneditprepare() function...
data.forEach((item) => {
var inputID = "node-input-mynode-dynamic-" + inputNo; //generate dynamic ID
var myNewRow = $('<div class="form-row" />');
parentDiv.append(myNewRow);
var myNewLabel = $(`<label for="${inputID}"><i class="fa fa-globe"></i> ${item.name}</label>`);
var myNewInput = $(`<input type="checkbox" class="mynode-dynamic-element" id="${inputID}" data-address="${item.address}" data-name="${item.name}" />`);
myNewRow.append(myNewLabel);
myNewRow.append(myNewInput);
inputNo++;
});
↑ NOTE how the input
has data-address and data-name and a specific class? The data items will be read from the element inside oneditsave
and the class name helps us read ONLY our dynamic elements. It must be unique/different to other classes in node-red.
- Store the values when user presses DONE button [client side HTML] Now you have DOM elements with appropriate values set, when the user presses "Done" button and
oneditsave
is called, itterate the items by using the class name you added to the dynamic elements, gather the values, build an array of objects, and lastly set node property you created in step1
oneditsave: function () {
var dynamicElements = $(".mynode-dynamic-element"); // use same class name as the dynamic DOM elements have
var dynOpts = []; //a temp array
dynamicElements.each( function(index,el) {
var name = $(el).data("name"); //get value of data-name from the dynamic element
var address = $(el).data("address"); //get value of data-address from the dynamic element
var checked = $(el).is(":checked"); //get checked true/false from the dynamic element
//make an object
var opt = {
name: name,
address: address,
checked: checked,
}
dynOpts.push(opt); //add object to array;
});
this.dynamicOptions = dynOpts; //update the node prop `dynamicOptions`
}
Once you have done all the client side stuff, you should be able to access config.dynamicOptions
in the constructor at server side JS...
On deploy, grab values entered at client side [server side JS]
Store the dynamicOptions passed in to the contructor somewhere you can get them later.
function myNode(config) {
RED.nodes.createNode(this, config);
var node = this;
node.dynamicOptions = config.dynamicOptions; //store config values in the node for later retreival
On msg
input, set payload and send [server side JS]
when a msg arrives in the on("input"
function, set payload and send the msg ...
node.on("input", function (msg, send, done) {
send = send || function() { node.send.apply(node,arguments) }
done = done || function(err) {
if(err){
node.error(err,msg);
}
};
msg.payload = node.dynamicOptions; //set payload to your dynamicOptions
send(msg); //send it