Woes with typedInput field and boolean default value

I'm trying to initialize a typedInput field with a boolean value of false, and I'm not managing. I prepared a minimal test-case to show the issue. The node HTML defines falsy values for 4 flags and then creates a typedInput field for all 4. The one I really care about is flag4, but only flag2 actually defaults to false. The difference between flag4 and flag2 is that the HTML element for flag4 is loaded dynamically. Here's the HTML:

<script type="text/javascript">
  RED.nodes.registerType('test inputtype', {
    category: 'testing',
    inputs: 1,
    outputs: 0,
    paletteLabel: "test inputtype",
    defaults: {
      name: { value: '' },
      flag1: { value: null },
      flag2: { value: false },
      flag3: { value: '' },
      flag4: { value: false },
    },

    oneditprepare() {
      // create typedInputs for flags 1, 2, 3
      for (const k of ['flag1', 'flag2', 'flag3']) {
        $("#node-input-"+k).typedInput({type:"bool", types:["bool"], typeField: "node-input-"+k+"-type"})
      }
      // load flag4's html dynamically and then create typedInput
      let url = `resources/@flexdash/node-red-fd-testnodes/inputtype.html`
      $('#dyn-load').load(url, () => {
        // after inserting into DOM, initialize the typed input fields
        for (const k of ['flag4']) {
          console.log(k, $("#node-input-"+k))
          $("#node-input-"+k).typedInput({type:"bool", types:["bool"], typeField: "node-input-"+k+"-type"})
        }
      })
    },
  });
</script>

<script type="text/html" data-template-name="test inputtype">
  <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>
  <div class="form-row">
    <label for="node-input-flag1">Flag 1</label>
    <input type="text" id="node-input-flag1">
    <input type="hidden" id="node-input-flag1-type" />
  </div>
  <div class="form-row">
    <label for="node-input-flag2">Flag 2</label>
    <input type="text" id="node-input-flag2">
    <input type="hidden" id="node-input-flag2-type" />
  </div>
  <div class="form-row">
    <label for="node-input-flag3">Flag 3</label>
    <input type="text" id="node-input-flag3">
    <input type="hidden" id="node-input-flag3-type" />
  </div>
  <div id="dyn-load"></div>
</script>

The resource file that gets dynamically loaded is:

<div class="form-row">
    <label for="node-input-flag4">Flag 4</label>
    <input type="text" id="node-input-flag4">
    <input type="hidden" id="node-input-flag4-type" />
</div>

And the visual result when I instantiate a widget is:

I expected all typedInput fields to show "false", but I really need flag 4 to show "false"... Also, the fact that the box of flag 4 has a different width is curious.

The JS file for all this is minimal:

module.exports = function (RED) {
  function testInputType(config) {
    RED.nodes.createNode(this, config)
  }
  RED.nodes.registerType("test inputtype", testInputType)
}

Steps to reproduce:

  • install @flexdash/node-red-fd-testnodes
  • instantiate a "test inputtype" node
  • open its config and see the values as in my screen shot

(You may want to hack package.json so it only installs the one test node type and omits the flexdash dependency.)

13 Mar 21:05:43 - [info] Node-RED version: v2.2.2
13 Mar 21:05:43 - [info] Node.js  version: v16.14.0
13 Mar 21:05:43 - [info] Linux 5.13.0-27-generic x64 LE

NB: I'm also having difficulties with the default values for typedInput fields of type json. Maybe it's the same issue. Specifically:

  • typedInput with { type: 'json', types: ['json'] } and default value null or "null": the input field is empty and outlined in red; since it's JSON I would expect it to show null and validate for one of the two versions of null.

the typedInput bool type defaults to true if there is no STRICT boolean equivalent of the default value set...

  • flag1: { value: null }, == true
  • flag2: { value: false }, == false
  • flag3: { value: ''}, == true

If you want to default to false, then either set the default value to false or add this to your loop...

$("#node-input-"+k).typedInput("value", !!this[k]); //note, wont work for default value of string "false"

Without seeing the static HTML or the code inside "// after inserting into DOM, initialize the typed input fields" I can only guess...

  • do the static fields have a width property or class?
    The width is copied from the HTML of the <input> by the typedInput when the widget is first created.

You can however call $("#node-input-"+k).typedInput("width", "calc(100% - 160px)") after creation to smarten them up.

1 Like

I guess it wasn't clear, I did post the code that gets dynamically loaded (it's 100% identical to that of flag2, except for "flag4" vs "flag2"):

<div class="form-row">
    <label for="node-input-flag4">Flag 4</label>
    <input type="text" id="node-input-flag4">
    <input type="hidden" id="node-input-flag4-type" />
</div>

Thanks for pointing out that I can set the value explicitly, that would be one work-around.

The inputs have no width set in any way in my code. I suppose the original input fields get their width calculated on first render and so the dynamically added one doesn't. The fun of calculated dimensions instead of using CSS...

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