Node config parameter not following default value

Hey there! I'm a bit clueless and hope you may be able to help me.

It concerns one of my nodes, node-red-contrib-smarthome-powerswitch. It's something pretty simple. Until now, the output's topic was always command and the payload either boolean true or false. So in the HTML file, I added:

RED.nodes.registerType('powerswitch',{
    category: 'Smart Home',
    color: '#C0DEED',
    defaults: {
        ...
        outputPayloadOnType: {value: "initval"},
        outputPayloadOn: {value: true},
        outputPayloadOffType: {value: "initval"},
        outputPayloadOff: {value: false}
        },
    ...
    oneditprepare: function() {
        ...
        if (this.outputPayloadOnType === 'initval') {
            $("#node-input-outputPayloadOnType").val('bool');
        }
        if (this.outputPayloadOffType === 'initval') {
            $("#node-input-outputPayloadOffType").val('bool');
        }
        ...
        $("#node-input-outputPayloadOn").typedInput({
            default: 'bool',
            typeField: $("#node-input-outputPayloadOnType"),
            types:['str','num','bool']
        });
        $("#node-input-outputPayloadOff").typedInput({
            default: 'bool',
            typeField: $("#node-input-outputPayloadOffType"),
            types:['str','num','bool']
        });
        ...

The idea was to have the initial values the same as the hardcoded values have been before the update. That is: boolean true for payload On and boolean false for payload Off.

Basically everything works. The only thing bothering me is that as soon as I update the node to the latest development version, it shows both boolean true for payload On and payload Off, as shown below:

image

This is inacceptable since after an update, the behaviour would be different than before the update.

The question is: Why does the field "Off Payload" also show true, eventhough it has a declared falseas default value (outputPayloadOff: {value: false})?

Link to the code before the update: GitHub - danube/node-red-contrib-smarthome-powerswitch at v1.0.11
Link to the node after the update: GitHub - danube/node-red-contrib-smarthome-powerswitch at v1.1.0

Hi @danube,
Perhaps I misunderstood this.

If you want bool as the default type why not define it directly in node.defaults?

I don't really understand what you mean by update? Did you remove your old node and use a new one (after upgrading), or do you just update? In the latter case, the default values no longer work because your node properties already exists. If Off payload is true before updating, the value will still be true after updating.

That should make it work "normally" (or I am misunderstanding your intent)

@GogoVega with "updating" I mean updating from a previous node version (1.0.10) to a newer one (1.1.0). Where the new version contains configuration parameters outputPayloadOn and outputPayloadOff which simply did not exist in the previous version but have been introduced in the new version.

Both of you @GogoVega and @Steve-Mcl suggest to clean the code accordingly. I don't know where I had the intention to use "initval". I remember when I learned to develop nodes, I looked into existing ones, so maybe I copied that from somewhere.

Whatsoever, the problem persists. The new code now is:

defaults: {
  ...
  outputPayloadOnType: {value: "bool"},
  outputPayloadOn: {value: true},
  outputPayloadOffType: {value: "bool"},
  outputPayloadOff: {value: false}
}
...
oneditprepare: function() {
  ...
  $("#node-input-outputPayloadOn").typedInput({
    typeField: $("#node-input-outputPayloadOnType"),
    types:['bool','str','num']
  });
  $("#node-input-outputPayloadOff").typedInput({
    typeField: $("#node-input-outputPayloadOffType"),
    types:['bool','str','num']
  });
  ...
}

Still, the dropdown in the UI configuraion shows true in both outputPayloadOn and outputPayloadOff parameters. Any clue?? :thinking::thinking:

If you add a new node, is Off Payload still true?

I should have mentioned that already, cause that seems to be a point... If I add it as a new node from the palette, outputPayloadOff indeed is false. Hence, this seems to affect only existing (and so, updated) nodes.

If outputPayloadOn is a new property, you don't have to do anything, the default value will be used. But you can check if node.outputPayloadOn exists then act accordingly
I believe your value is true because you tested in dev, so you added this value to your node

The thing is, this seems not to be true! The new parameters have both been given a default value.

  outputPayloadOn: {value: true},
  outputPayloadOff: {value: false}

Now these default values are present if the node is being newly created from the palette. But if you're coming from a previous version of the node (where those two new parameters have not yet been introduced) and updating to the new version (with the two new parameters), it shows true in both parameters. Now I'm concerned about those who update and end up with a non working node unless the parameter has been changed manually.

Not quite

Default values are only applied for newly created nodes introduced into the flow - not for nodes that are already deployed.

Defaults are applied when a node is dragged into the editor - at least that is my experience.

If there are new properties, the default values (of these properties) will be used but a deployment (and therefore a modification of the node) is necessary.

You can test it by exporting your node: look before then after modifying it.

No.

Defaults are only used when a new node has not had its configuration written yet.

Here is an example.

  1. Drag in a delay node you can see the default is 5 seconds.
  2. Import the below.
    Its a delay node where it doesn't have (lets pretend a timeout set) - I removed it from the JSON
[{"id":"e041bf92aea566c9","type":"delay","z":"2d7bf6e3.84c97a","name":"","pauseType":"delay","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":160,"y":695,"wires":[[]]}]

You will see the default of 5 is not set, Evan though it is default, in the HTML definition.
Evan if you open up the node after a deploy - it still does not set the default.

I have only witnessed the defaults being set when dragged into the editor, and it seems that is the only time defaults are used

Strange, need to check why :thinking:

So check if node.outputPayloadOn exists then set value

1 Like

Yup!

For new properties I have introduced in my nodes, after they have been deployed, I have to do this - by asking users to open up the node, then save/deploy - so I can check and populate the value in oneditprepare if its not set.

But for new users, they don't - as the defaults will kick in when dragged into the flow.

But in reality - I tend to save these changes for major version bumps, as technically they are breaking changes - especially if the new values are depended on

If these new properties are required for your logic, the “correct” way is to major version bump, and provide the documentation that explains how to fix/address the breaking change.

Hi @danube,
Indeed when you add a new property to a node, that won't exist on existing nodes. So you always have to deal with 2 cases:

  • html file: When the user opens the config screen of such an old node, you have to set explicit (with a js statement) the default value if the property does not exist yet, and show that default value.
  • js file: When the user does NOT open the config screen, then the backend of your code also needs to set the default value if the property does not exist yet. To make sure that existing nodes process input messages correctly.

See more info here.

Bart

This has transitioned to a Feature Request for further discussion.

FR: Populate default value to new node property even if the node already exists - Core Development / Feature Requests - Node-RED Forum (nodered.org)

1 Like

I did some crossreading through the links you folks provided, thank you so much for that. I accept that thinks are as they are, at least for the moment. Nevertheless, I strongly vote for the statement that defaults should be given priority for newly introduced properties.

Now, I simply don't understand yet, why both my parameters show true as selected value after I open the node properties the first time after updating. They both may also show false, so there's for sure some explaination (which at this point I'm secondarily interested in...).

Now I'm forced to find a way around this behavior anyways, no matter if there will ever be a core change regarding that. @GogoVega in one of your posts you provided an approach I also had in mind:

oneditprepare: function() {
    console.log("DEBUG: VALUE IS " + this.outputPayloadOff)
    if (this.outputPayloadOff === undefined) {
        $('#node-input-outputPayloadOff').val('FALSE');
    }
}

I expected that if the configuration has been opened the first time after an update (when the newly introduced parameter still does not exist hence is undefined) the appropriate parameter value will be set to false. I added a console.log to verify this.

Now the first time I open the configuration, I (weehaa!) get:

DEBUG: VALUE IS undefined

JQuery should set the value to false but in the boolean dropdown it still shows true. I acknowledged that by okaying the dialogue and at second opening I (boooh!) get:

DEBUG: VALUE IS true

I understand that I also have to capture that undefined in JS in the case the node properties have never been opened, but seems I'm stuck here already. Any clue, why my value is not being set to false?

I slept on it. The behavior makes sense. With $('#node-input-outputPayloadOff').val('FALSE'); I'm trying to set the value of the new property outputPayloadOff, which simply doesn't exist yet at the time of oneditprepare. It is only created when the user confirms the configuration dialog, but then it simply makes no more sense to check it against undefined as it has been set to true by whatever mechanism.

I'm really stuck here. If I introduce this update, careless users will end up in a situation where the installation doesn't work.

Now I am not afraid of those who simply update without opening the configuration. In JS I can check if the parameters are available or not and work accordingly.

I am more concerned about those who update the node and, at some later point, open the configuration and edit something differently without paying attention about those new parameters at the very bottom. Once deployed, the installation will behave problematically.

Raising the major version feels more like a poor excuse to me.

Any idea how to work around this?

Hi,
Should be:

$('#node-input-outputPayloadOff').val('false');
//or
$('#node-input-outputPayloadOff').typedInput('value', 'false');

EDIT: It's a string

1 Like

Are you up 24/7??

$('#node-input-outputPayloadOff').typedInput('value', 'false') is the working solution where the upper suggestion $('#node-input-outputPayloadOff').val('false'), for whatever reason, does not work. Now that's the workaround of my choice. Still, it feels like a workaround and I honestly think that defaults should apply also to newly introduced parameters.

Thanks to all of you for your efforts, @GogoVega for the workaround code.

EDIT: Doesn't matter if false or 'false', both work. :wink:

1 Like