TypedInput Select Box

After researching code, reading docs and trial & error. I think I finally have a handle on Select Box. I am sharing my discovery for others and to start discussion on what changes could be made (documentation or code) to Select Box.

<style>
  .choose-text .red-ui-typedInput-option-label:empty::after {
    content: "-- Choose an Option --";
  }
</style>

<script type="text/html" data-template-name="example">
  <div class="form-row">
    <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
    <input type="text" id="node-input-name" placeholder="Name">
  </div>

  <!-- Class 'choose-text' for the default Select Box text -->
  <div class="form-row choose-text">
    <label for="node-input-multiple"><i class="fa fa-id-times"></i> Multiple</label>
    <input type="text" id="node-input-multiple">
    <input type="hidden" id="node-input-multiple-type">
  </div>

  <!-- Class 'choose-text' for the default Select Box text -->
  <div class="form-row choose-text">
    <label for="node-input-string"><i class="fa fa-id-file-text"></i> String</label>
    <input type="text" id="node-input-string">
  </div>

  <!-- Class 'choose-text' for the default Select Box text -->
  <div class="form-row choose-text">
    <label for="node-input-number"><i class="fa fa-id-hashtag"></i> Number</label>
    <input type="text" id="node-input-number">
  </div>

  <!-- Class 'choose-text' for the default Select Box text -->
  <div class="form-row choose-text">
    <label for="node-input-boolean"><i class="fa fa-id-bold"></i> Boolean</label>
    <input type="text" id="node-input-boolean">
  </div>
</script>

<script type="text/html" data-help-name="example">
  <p>Used to test SelectBox.</p>
</script>

<script type="text/javascript">
  RED.nodes.registerType('example', {
    category: 'function',
    color: '#000000',
    defaults: {
      name: { value: '' },
      multiple: { value: '' },
      multipleType: { value: '' },
      string: { value: '' },
      number: { value: 0 },
      boolean: { value: true }
    },
    inputs: 1,
    outputs: 1,
    label() {
      return this.name || 'SelectBox Example'
    },
    paletteLabel() {
      return this.name || 'SelectBox Example'
    },
    icon: 'font-awesome/fa-exclamation-circle',
    oneditprepare() {
      const node = this
      const { string, boolean, number, multiple, multipleType } = node

      $('#node-input-string').typedInput({
        // It is important to have a value for type and that the
        // array types value has the same otherwise you can have
        // redrawing issues.
        type: 'string', 
        types: [
          {
            // Best to match property type above
            value: 'string',
            // Sets the default value but only works if you
            // are working with strings
            default: string,
            options: [
              {
                value: 'foo',
                label: 'Foo'
              },
              {
                value: 'bar',
                label: 'Bar'
              }
            ]
          }
        ]
         // Set the current value
      }).typedInput('value', string)

      $('#node-input-number').typedInput({
        type: 'number',
        types: [
          {
            value: 'number',
            // Should set the default value but only works if you
            // are working with strings will not accept any type.
            default: Number(number),
            options: [
              {
                value: 1,
                label: 'One'
              },
              {
                value: 2,
                label: 'Two'
              }
            ]
          }
        ]
         // Sets the current value will only work if same type
      }).typedInput('value', Number(number))

      $('#node-input-boolean').typedInput({
        type: 'boolean',
        types: [
          {
            value: 'boolean',
            // Should set the default value but only works if you
            // are working with strings will not accept any type.
            default: boolean === "true",
            options: [
              {
                value: true,
                label: 'True'
              },
              {
                value: false,
                label: 'False'
              }
            ]
          }
        ]
         // Sets the current value will only work if same type
      }).typedInput('value', boolean === "true")

      // This is an experiment if there are multiple types (see image).
      $('#node-input-multiple').typedInput({
        default: multipleType, // This defalut refers to the 'type' value.
        type: 'multiple',
        types: [
          {
            value: 'multiple',
            default: multiple, // This defalut refers to the 'options' value.
            options: [
              {
                value: 'ant',
                label: 'Ant'
              },
              {
                value: 'bear',
                label: 'Bear'
              }
            ]
          },
          {
            value: 'anothermultiple',
            default: multiple, // This defalut refers to the 'options' value.
            options: [
              {
                value: 'cat',
                label: 'Cat'
              },
              {
                value: 'dog',
                label: 'Dog'
              }
            ]
          }
        ],
        typeField: '#node-input-multiple-type'
      }).typedInput('value', multiple)
    },
    oneditsave() {
      const node = this

      node.multipleType = $('#node-input-multiple-type').val()
    }
  })
</script>

I think it would be nice if default worked with a type other then string and since the value is returned as a string no mater the type, I feel, you should be able to set with a string value.
I did not have a use for the Multiple Example I just noticed the functionality and so included what I had discovered.

Thanks for sharing.

I did update the TypedInput docs last week to include examples for Select and Multi-Select.

https://nodered.org/docs/api/ui/typedInput/#examples

Had you found those docs? Were they useful? If you think anything could be clearer, do let us know.

1 Like

@knolleary it was a good thing that you added those docs for Select or I would have been more lost how to use typedInput for a Select when I did. The complications I ran into was;

  1. How to retain the value on reload - That the default belongs in the array item and only works if the options property value is a string. If using .typedInput('value', value) the value must be of the same type even though the stored value became a string.
  2. The importance of the connection of the type property to the array item property value.
  3. How to start with no value (I have not solved this one yet) so that the Select is initially blank or displays a placeholder like '-- Select One --'

Are you basing on the fruit example? If so, you can add it as the first of your options:

        { value: "none", label: "-- Select One --"},
        { value: "apple", label: "Apple"},
        { value: "banana", label: "Banana"},
        { value: "cherry", label: "Cherry"},

@chris.willing - Thanks for the suggestion. The solution I am using now is to follow the setup of the typedInput with a call to set the value to something not in the options array this causes the dropdown to start with blank. This method does not require another option but does not have the text.

I updated my code in the initial post to have a "placeholder" for the select box. It is two steps first is to follow the setup of the typedInput with a call to set the value to something not in the options array this causes the dropdown to start with blank. Second is to add a class to the div form-row, in my example I used 'choose-text' <div class="form-row choose-text"> then I set the following css:

<style>
  .choose-text .red-ui-typedInput-option-label:empty::after {
    content: "-- Choose an Option --";
  }
</style>

Incase I was unclear in my previous post. My main reason for posting this thread is for documentation, for others to be able to find more info on Select Box.

1 Like