Hello,
I am looking to create a node that is similar to the filter node, from a dynamically changing editor perspective.
My end goal is to have attributes change depending on what I have previously chosen.
For example: if in the first attribute i choose between 3 different options: (Car, Person, Building). The other attributes shown should change accordingly.
For example: For if I choose Car, I want to have labels and attrbiutes show for the Car (Make, type, year) and if I choose person I want to labels and attributes show for the person (Name, Job, Social SecutiryID), and so on.
It is kind of similar to what is implemented in the built in the filter function. For example if I choose first the mode as 'block unless value changes', I get different things that if I choose the mode as 'block if value change is greater than'.
I have tried to read through the source code of the filter node but it was a bit complicated. for example in the labels, defined in the editor, there are 'rbe.label.func'. In the Creating you own nodes tutorial, the example shown is very basic, with static properties.
I am still a beginner, and therefore can't grasp the complexity of the source code to come up with something on my own.
I would be interested to know the structure behind creating such dynamics nodes or how is it conceived.
Also for example, in the filter node options, the options that I see in the nodered editor are not explicitly stated in the html file, instead they are replaced by 'rbe.opts.deadbandEq' or 'rbe.opts.deadband'. I would be interested in knowing how to replicate such behavior in a very simple example.
Thanks @jbudd for your suggestion. However, I am looking to implement this in the node itself internally. Since some of the core nodes (for example: filter) offer this functionality without any switch nodes or manipulation, I am positive I can have everything done in the node itself internally (in the html and json files).
I have implemented some functionality where I am able to hide/show some text input boxes based on the input of the first option selected, however, updating the labels is still problematic.
I can create a minimal example flow that would represent what I want to achieve if it would be more helpful to solve the problem.
Thanks @knoepsche however, I think this workaround would be my last option, and I am pretty sure I can achieve dynamic configuration, since it is already implemented.
Note that you have access to jQuery in the node's html file so this is pretty easy.
The easiest way is to define all of the possible fields but mark the ones that you don't want to see as hidden - jQuery has a function to assist with that but really it is just changing the CSS style. You could also define some CSS classes if you wanted to.
Simply group each set of fields inside a <div> with a named id then you can turn on and off all of them together.
While this is a viable solution, I was wondering if I could have a more automatic solution since in my real application I have more than 80 options that I can choose from first, each of which that might give rise to 3 or 4 different additional input boxes below. This would translate to around 250+ fields defined, which is my last resort.
I am trying to do it by defining the messages.json file as the one used by the core modules. I am however, unsure how I will pass a variable to the data-i18n argument in the corresponding label. As an example you can check the following:
from: Filter node
and these are the corresponding values that is has defined:
"rbe": {
"rbe": "filter",
"label": {
"func": "Mode",
"init": "Send initial value",
"start": "Start value",
"name": "Name",
"septopics": "Apply mode separately for each ",
"gap": "value change",
"property": "property",
"topic": "topic"
},
"placeholder": {
"bandgap": "e.g. 10 or 5%",
"start": "leave blank to use first data received"
},
"opts": {
"rbe": "block unless value changes",
"rbei": "block unless value changes (ignore initial value)",
"deadband": "block unless value change is greater than",
"deadbandEq": "block unless value change is greater or equal to",
"narrowband": "block if value change is greater than",
"narrowbandEq": "block if value change is greater or equal to",
"in": "compared to last input value",
"out": "compared to last valid output value"
},
"warn": {
"nonumber": "no number found in payload"
}
My plan is to have the parameter passed to data-i18n configured based on the option that I chose first. Still in the process of figuring out if this is actually feasible.
So that is "simply" a case of moving the processing into a function and devolving the data to an object instead of pre-defining in the html. jQuery makes that fairly easy as well.
Not sure how the data-i18n stuff works, you probably need input from Nick or Steve for that.
But in principal, all you need in your edit prep function is to define an on-change listener on the select that calls a function to dynamically create the html based on your lookup object and the value from the select.
You don't really need the data-i18n attributes since you could just as easily put that information into your lookup object.
That was my first option and plan. I have already defined an on-change listener that stores the first option that I selected, and gets the other attributes that I want to display next. My problem is the dynamic creation of the html.
All I want to do is basically change the labels of the input text boxes that appear to have the same values as the attributes that I get. But for some reason, I am not able to set the label dynamically (I think it's my poor html knowledge) and googling didn't help since it's such a specific topic.
So to keep up with the example that I posted in the beginning. If i choose Car as the first option, I want the dialog to have 3 text boxes, each with the corresponding label (Make, Type, Year).
in my oneditprepare function, I already have 'Make', 'Type', and 'Year' in variables, but I can't transfer them to the html dynamically.
Are you aware of the syntax used? I think it's much less trouble than going through the data-18n thing as you said, and it is the right way to do it.
OK, so to change the labels using jQuery, you need suitable selectors. The easy way is to add an id attribute to each label then use the selector #labelid1 or whatever id you gave. To change the label, you can use something like $('#labelid1').text('My new Label').
The problem though is that you are now repurposing the input field. If you are using the default input fields that node-red uses, they map to properties that will be passed to your node's runtime when you press the deploy button. Not really a big problem but of course, you need some suitable processing in the node runtime js file to make sense of the input.
Thank you @TotallyInformation ! I have achieved part of what I want thanks to your tips. I will take care of the processing in the node's js file for the input.