TypedInput Widget

Hi,

Node-RED provides a nice editor widget for selecting and defining for example payload types as strings, numbers, JSON (with editor) etc.

In case you want to do it yourself, here a little example node.

js file

module.exports = function(RED) {
  "use strict";

  function simpleChange(config) {
    RED.nodes.createNode(this, config);
    var node = this;
    node.config = config;
    
    node.on('input', function(m) {
      m.payload = RED.util.evaluateNodeProperty(node.config.changeValue, node.config.changeValueType, node); 
      if(node.config.topic !== '') {
        m.topic = node.config.topic;
      }
      node.send(m);
    });
  }
  RED.nodes.registerType("simpleChange", simpleChange);
}

html

<script type="text/javascript">
  RED.nodes.registerType('simpleChange', {
    category: 'function',
    color: '#2176F3',
    defaults: {
      changeValue: {
        value: true, 
        required: true, 
        validate: RED.validators.typedInput('changeValueType')
      }, 
      changeValueType: {
        value: 'bool'
      },
      topic: {
        value: ''
      },     
      name: {
        value: ''
      }
    },
    inputs: 1,
    outputs: 1,
    icon: "hash.png",
    label: function() {
      return this.name || '';
    },
    oneditprepare: function() {
      $('#node-input-changeValue').typedInput({
        default: 'bool',
        typeField: $("#node-input-changeValueType"),
        types: ['bool','str','num','json','bin']
      });
    }
  });
</script>

<script type="text/x-red" data-template-name="simpleChange">
  <div class="form-row">
    <label for="node-input-changeValue">Change to</label>
    <input type="text" id="node-input-changeValue" style="width:70%">
    <input type="hidden" id="node-input-changeValueType">
  </div>
  <div class="form-row">
    <label for="node-input-topic">Topic</label>
    <input type="text" id="node-input-topic">
  </div>
  <div class="form-row">
    <label for="node-input-name"><i class="icon-tag"></i> Name</label>
    <input type="text" id="node-input-name" placeholder="Name">
  </div>
</script>

2 Likes

Thanks, that's actually really useful.

Would you mind explaining a little about what's actually going on here (and what the result looks like)?
I'm not really clear what you are doing in the validator, or with the hidden field.

I also just baked this together from existing nodes, so hopefully I do not write garbage. In this case, one of the Node-RED creators has to correct me.

So basically there is an input field <input type="text" id="node-input-changeValue"> with id node-input-changeValue. This is where the actual value is typed into. However, if you want to use the built in editor widget for changing the type, you add this <input type="hidden" id="node-input-changeValueType"> field to it, which will create the dropdown and also for example the json editor etc.
In order to enable the functionality, you need the typeInput method, which is invoked when the node property editor is opened (oneditprepare). default: 'bool' says that the default type is a boolean, I also added changeValueType: { value: 'bool' }, although I am not certain if this is necessary (seems a bit redundant). The property typeField: $("#node-input-changeValueType") specifies the id of the hidden input. The types property allows you to state which types are available to choose from. There are more available, look for example in the inject node src.

The result will look like in the inject node, where you can select a type of property you want the user to type into your input field. If you choose json for example, then additionally there will be a button which allows you to open the json editor.

validate: RED.validators.typedInput('changeValueType') is a validator that checks if the typed in value is of valid selected type.

Finally, what you type in will be availbale in the changeValue property, represented as a string. To convert it to the type you have selected, there is the util function RED.util.evaluateNodeProperty(node.config.changeValue, node.config.changeValueType, node);

Hope that helps.
If you have additonal questions, please ask, but probably Nick has to answer them :slight_smile:

2 Likes

if you only want json, you can set types to ['json']and remove typeField: $("#node-input-changeValueType") and also the hidden input.

OK, cool. thanks, I'll give it a shot.

Hi there, so when i select "msg" as desired type then i have to insert an if of switch in the "node.on" method so i set the msg.payload to the desired value of property? Or is there a simpler way?

I'm a wee bit stuck here. I have a node that I added the typeField to, however, the typeField never saves. Thoughts?

Do you have a default entry that matches the name of the widget?

e.g...
image

image

Alternatively, you can set the value in oneditsave()

Pretty late here but I just ran up against the exact same problem and figured it out. You need to create a default for the "type" field as well as the value field in your defaults defined in the html file. So in @cinhcet 's example above it's this bit that's important:

changeValue: {
  value: true, 
  required: true, 
  validate: RED.validators.typedInput('changeValueType')
}, 
changeValueType: {
  value: 'bool'
},

My problem was I had the changeValue field but not the changeValueType field so the type was never saving. It's also not very clear from the documentation that this is necessary although it seems obvious after I figured this out. Hope this helps anyone who experiences similar difficulty.

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