Does typedInput save typed values?

I'm always confused about what typedInput saves into the node and wonder whether I'm doing something wrong or this is as-designed...

If I have a typedInput and select the number type or boolean type, will the node get a javascript Number respectively boolean or will it get a string with the number respectively a string with "true"/"false"?

I built a minimal test-case which suggests that the value saved is always a string and thus the node implementation has to make the conversion to the intended type. Is this correct or am I simply missing a trick?

typedinput-test.js:

module.exports = function(RED) {

  function typedinput_test(config) {
    RED.nodes.createNode(this, config)
    console.log("typedinput_test", JSON.stringify(config))
  }

  RED.nodes.registerType("typedinput test", typedinput_test)
}

typedinput-test.html:

<script type="text/javascript">
  RED.nodes.registerType('typedinput test', {
    category: "tests",
    color: "#FFFF00",
    defaults: {
      name:  {value:""},
      test_string:{value:"default string", required:true},
      test_number:{value:125, required:true},
    },
    inputs: 0,
    outputs: 1,
    icon: "font-awesome/fa-th",
    paletteLabel: "typedinput test",

    label() { return this.name || "typedinput test" },

    oneditprepare() {
      console.log("oneditprepare", this)
      $("#node-input-test_string").typedInput({
        type:"str",
        types:["str","num","bool"],
        typeField: "#node-input-test_string-type"
      })
      $("#node-input-test_number").typedInput({
        type:"str",
        types:["str","num","bool"],
        typeField: "#node-input-test_number-type"
      })
    },
  });
</script>

<script type="text/html" data-template-name="typedinput test">
  <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>
  <div class="form-row">
    <label for="node-input-test_string">Test string</label>
    <input type="text" id="node-input-test_string" />
    <input type="hidden" id="node-input-test_string-type" />
  </div>
  <div class="form-row">
    <label for="node-input-test_number">Test number</label>
    <input type="text" id="node-input-test_number" />
    <input type="hidden" id="node-input-test_number-type" />
  </div>
</script>

<script type="text/html" data-help-name="typedinput test"></script>

The edit panel comes up:
image

I change it:
image

I deploy and the node prints:

typedinput_test {"id":"f553feb13caf2a2d","type":"typedinput test","z":"451d9acba8e52c2f","name":"",
"test_string":"true","test_number":"44",
"x":680,"y":480,"wires":[[]]}                                                                           

And I see that both test_string and test_number have string values.

Yes it should be remembered.

See this post: Node Creation oneditprepare - #2 by Steve-Mcl and the solution 2 posts below.

In short, while the values might be saved as string, using the RED.util function knows how to restore the correct value and type selected by the user.

It will only be remembered if you've added the appropriate property to your defaults object to store the type value in.

For your example code, that would be test_string-type and test_number-type

Which piece of documentation did I miss?

So I changed the defaults to:

      test_string:{value:"default string", required:true},
      'test_string-type':{value:"str"},
      test_number:{value:125, required:true},
      'test_number-type':{value:"num"},

But the output from my node is still:

typedinput_test {... ,
  "test_string":"true","test_string-type":"bool",
  "test_number":"36","test_number-type":"num" ,...}                        

So this doesn't really solve the problem...

Ok, so finally this does it:

  function typedinput_test(config) {
    RED.nodes.createNode(this, config)
    console.log("typedinput_test", JSON.stringify(config))
    console.log("Typed test_string:",
      RED.util.evaluateNodeProperty(config.test_string, config["test_string-type"], this))
    console.log("Typed test_number:",
      RED.util.evaluateNodeProperty(config.test_number, config["test_number-type"], this))
  }

produces

Typed test_string: true                                                          
Typed test_number: 34                                                            

:thinking:

This came up in another thread a couple days ago. I realise it is a bit of inferred information that needs to be made more explicit. It's on my list of doc updates I'm going to try to make in the coming days.

Likewise the info on evaluateNodeProperty.

I don't intend to pile on, but the conversion to strings after saving values in the configuration menu cost me more time than writing the backend code. I eventually gave up on trying to figure out why my booleans and numbers arrived as strings on the backend, so I just started checking if value !== 'false' or using parseInt to get the values I needed on the backend and ran with it. Obviously, my lack of understanding was the problem, but man oh man, did I really try to get that boolean to arrive :sweat_smile:

Oh, I cannot count the number of hours I've wasted on trying to get typedInput to work in a reasonable manner nor the number of hours trying to reverse engineer what it does and looking for the non-existant code that would make the types right. Anyone who thinks this design is nice or user friendly lives in a separate universe from mine...

yes - we live in a universe where we think supportive comments offer much more encouragement for developers to write documentation.

7 Likes

I just wanted you to know that I am very fond of you and the great work that you do :heart_eyes:. If you ever see any thing that I post and you are unsure of my attitude, just know that I am either trying to be joky or maybe a little sarcastic. I have tried to include emoticons to help relay my feelings, but as my wife has told me many times, when I talk to people I sound like I want to fight :rofl:. And to further extend how sensitive I have tried to be lately, I feel that I found a bug in the editor but not once did I use the word bug in my recent post.

Yes - 2022 has been a long long year. A lot has been accomplished, and a lot of progress made. On a project that is ever changing and growing there will always be parts that get overlooked or left behind, and bugs to be found :wink: - but it is often the same set of hands that ends up spinning all the plates. As long as we are all helping to pull in the same direction (which I think we are most of the the time) then I'm sure we will make everything better for everybody.

3 Likes

I appreciate your comment and want to apologize for having vented. Sometimes calling a spade a spade also has its merits. Documentation would help. Revising the functionality might help more, though... (Moving away from jquery DOM hacking might help even more, but that argument is for another day.)
At least I've contributed a possible complete end-to-end example for the docs above...

2 Likes

NP - we all have to vent from time to time. As usual sometimes designs "evolve" and what started as a good idea doesn't really stand the bright light of hindsight. So yes alternatives can always be discussed, but need to be mindful of breakage and migration especially when it's such a core piece of functionality. And indeed docs like PRs too.

And thanks or all your efforts on flexdash - it feels like it's really starting to take shape.

2 Likes

Glad to see we're all friends again :innocent:

1 Like

I have added some docs on the handling of typeField: TypedInput Widget : Node-RED

And on how to parse the values in the runtime side: TypedInput Widget : Node-RED

3 Likes

Niice!

Q: these two parts of the example don't fit together, right? (mismatch in element selectors)

$(".input").typedInput({
    typeField: ".my-type-field"
});

and

<div class="form-row">
    <label>Example:</label>
    <input type="text" id="node-input-myField">
    <input type="hidden" id="node-input-myFieldType">
</div>

The html goes with the more complete JavaScript example below it that shows it in the context of a node definition.

from the updated docs:
"Due to the way the typedInput enhances a regular HTML <input> , its value is stored as a string."

That line right there will save many new devs from trying to figure out why they are getting strings. Thank you.

1 Like