Simple HTML Forms with uibuilder

A very common requirement for a Node-RED based system is a need to get some user input. Most people turn to Dashboard for this. However, if you need multiple different inputs, you have to build them all into the same "app". Not so if you use uibuilder. Then you can build the simplest of web apps for each requirement if you wish either by having multiple uibuilder nodes or one node with multiple pages.

But how to create a form and get the data back into Node-RED easily - especially if your knowledge of HTML is limited? Well, this FAQ may help. :grin: In addition, I'm also creating another video for those who prefer that approach to learning.

Note that this will work with uibuilder v6.0 (and probably with v5 as well). v6.1, when it is released, will make this even easier with some zero-code features.

Step 1: Deploy a new or use an existing uibuilder node. Make sure you have at least a debug node on the top output port.

Step 2: Make your index.html file look like this:

<!doctype html>
<html lang="en"><head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Simple Form - Node-RED uibuilder</title>
    <meta name="description" content="Node-RED uibuilder - Simple Form">
    <link rel="icon" href="./images/node-blue.ico">

    <!-- Your own CSS (defaults to loading uibuilders css)-->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all">

    <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / - socket.io no longer needed  -->
    <script defer src="../uibuilder/uibuilder.iife.min.js"></script>
    <script defer src="./index.js">/* OPTIONAL: Put your custom code in that */</script>
    <!-- #endregion -->

</head><body class="uib">

    <form>
        <div>
            <label for="name">Name:</label>
            <input id="name" />
        </div>
        <div>
            <label for="mail">Email:</label>
            <input type="email" id="mail" />
        </div>
        <div>
            <label for="msg">Message:</label>
            <textarea id="msg">Some text here</textarea>
        </div>
        <div class="button">
            <button onclick="fnSendToNR(event)">Send your message back to Node-RED</button>
        </div>
    </form>

</body></html>

Noting the onclick attribute which calls a function we will put into index.js. It passes a "magic" HTML variable called event, we don't have to create that.

Step 3: Make your index.js file look like this:

function fnSendToNR(event) {
    // Stop the button doing the default action
    event.preventDefault()

    // Grab all of the values from the form
    const form = {}
    if ( event.srcElement && event.srcElement.form) {
        Object.values(event.srcElement.form).forEach( frmEl => {
            form[ frmEl.id ] = frmEl.value
        })
    }

    // Get the data back to Node-RED
    uibuilder.send({
        'topic': 'msg-from-uibuilder-front-end',
        'payload': form,
    })
}

Hopefully, you can see that the only vaguly complex bit of code is the if statement and loop that grabs the form values. In uibuilder v6.1, you won't need any of this code and will be able to use <button onclick="uibuilder.eventSend(event)"> in your HTML with no JavaScript at all.

There is, of course, lots more you could do to finesse this but those are the basics. Add some CSS to better format the form (plenty of examples on the Internet) and you are good to go.

Add a response message <div> somewhere and populate from messages from node-red if you want to do form validation in Node-RED rather than in front-end JavaScript or give other messages to the user.

Hope you find this useful? Let me know either way. :upside_down_face:

Just to say, I do find these little snippets interesting. This one appears to have a spare "":"" but I can't see why

{"topic":"msg-from-uibuilder-front-end",
 "payload":{"name":"Fred",
            "mail":"Bloggs",
            "msg":"A Message",
            "":""},"
_socketId":"Nqm5jsKsaY253UNDAAA5","_msgid":"f7f299582ac83879"}
1 Like

Nicely spotted! I wondered if anyone would comment on that. :grin:

It is because HTML considers a button to be an "input" and so it is included in the form property.

However, because I don't put an id or name on the button in the example, and because a button does not have a value property, you get the strange object property with a blank string as a key name. Probably most people don't even realise that JavaScript allows an object property with an empty string as a name!

Anyway, it is "valid" but pointless of course. In uibuilder v6.1, I've included the form data in the eventSend function and you will be glad to hear that I've filtered that spurious entry out. But in this example, I decided to leave it alone and see if anyone picked up on it. I'll leave it as an exercise for the readers to work out how to get rid of it if it bothers you.

Anyway, thanks for following along. And, as always, if there is an example you'd like me to cover, just let me know.

Well since you are asking :grin:. I am using the Network Monitor flow that you published ages ago and would like an updated version of the table that came with it (not using Vue)

Does that have the edit fields?

The new uib-element node in the v6.1.0 branch has a table output but it is still very basic. But the nice thing about it though is that it outputs config data that can be enhanced separately. In addition, we can use these to quickly create some nice HTML that we can then save and build on.

I've got plans for a tabbed interface output for that node as well. I've spotted a couple of useful examples that I can build on.

So editable tables might be a short ways off yet :grin: But, they are high on my agenda because the ability to use a node to create even a basic editable table from simple input data would be massive I think. It's just there's a lot to think about.

It does. Look forward to the result. And thank you for all the work you have put into this.

This topic was automatically closed after 30 days. New replies are no longer allowed.