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. 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.