Request example to have button disabled when uibuilder.onchance

I've got the uibuilder simple example running.
Now I'd like to be able to control the button on the front-end side depending on uibuilder (either onchange or node-red msg)

hopefully my request is clear.

Indeed, not so much...

Anyway, using uibuilder implies knowing how to code a web-app. You can find a lot of documentation on the latest version here.

Then, if you have more specific question, please add your code snippets.

Hi, welcome to the community.

If you could explain a little more about the outcome you are trying to achieve, that may let us help you more.

I started with this example:

it works, easy to get it going.
I want to be able to alter / modify / update the web ui - for instance, I want to be able to disable or hide the button.

I saw this ("msg._ui.method - update") here:

but I just couldn't seem to follow the info.
would love to have a working example - if this will accomplish the above.
thanks.

Perhaps this example may be of use to you. It demonstrates the use of a uibuilder sending and receiving messages.

[{"id":"da65bd5fe4671fb9","type":"inject","z":"86a82b7c66374659","name":"8 All","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"passwordLength\":8, \"uppercase\":true, \"lowercase\":true, \"numeric\":true, \"special\":true}","payloadType":"json","x":130,"y":120,"wires":[["632f590dbee6c4ca"]]},{"id":"c215fb7168aec76f","type":"debug","z":"86a82b7c66374659","name":"data from ui frontend","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1080,"y":200,"wires":[]},{"id":"3f17a01b27448d27","type":"debug","z":"86a82b7c66374659","name":"control msgs from ui","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1080,"y":280,"wires":[]},{"id":"632f590dbee6c4ca","type":"uibuilder","z":"86a82b7c66374659","name":"","topic":"","url":"passgen","fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"templateFolder":"blank","extTemplate":"","showfolder":false,"reload":false,"sourceFolder":"src","deployedVersion":"5.0.0","x":330,"y":240,"wires":[["279cda872a7db8d4"],["3f17a01b27448d27"]]},{"id":"ebbea50cc89b8d06","type":"json","z":"86a82b7c66374659","name":"","property":"payload","action":"","pretty":false,"x":670,"y":200,"wires":[["7d7da6797b4d10f9"]]},{"id":"b6c72648ca774348","type":"switch","z":"86a82b7c66374659","name":"","property":"payload","propertyType":"msg","rules":[{"t":"istype","v":"json","vt":"json"},{"t":"eq","v":"","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":3,"x":550,"y":220,"wires":[["ebbea50cc89b8d06"],[],["7d7da6797b4d10f9"]]},{"id":"6bf45b4a1ddd4124","type":"comment","z":"86a82b7c66374659","name":"index.js","info":"/* eslint-disable strict */\n/* jshint browser: true, esversion: 6, asi: true */\n/* globals uibuilder */\n// @ts-nocheck\n\n/** Minimalist code for uibuilder and Node-RED */\n'use strict'\n// LINES ABOVE ARE FOR UIBUILDER AND NODE-RED\n\n\n\n// Assignment code here\n\n// After button clicked, prompt to select password criteria\nvar confirmcriteria = window.alert(\"Select criteria to include in the password: length, character types.\");\n\n// Declare global variables and constants \nvar characterTypes = \"\";\nconst Uppercase = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\nconst Lowercase = \"abcdefghijklmnopqrstuvwxyz\";\nconst Numeric = \"0123456789\";\nconst Specialchar = \"~!@#$%^&*()_+=-{}[]|:\\\";'<>?,./`\";\n// set passwordLength to an object that represents a number\nvar passwordLength = new Number;\n\n// Sets the length of password to generate\nfunction setPasswordLength() {\n    // Get the length from user input\n    passwordLength = window.prompt(\"Choose the number of the length for characters (at least 8 characters and no more than 128 characters)\");\n    return passwordLength;\n};\n\n// Run the function\nsetPasswordLength();\n\n// Choose which characters to include\nfunction charDialog() {\n    // If password length is greater or equal to 8, and less than or equal to 128\n    if (passwordLength >= 8 && passwordLength <= 128) {\n        var upperConfirm = window.confirm(\"Do you want to include uppercase characters?\");\n        // Check if selection has been made\n        if (typeof upperConfirm == \"boolean\") {\n            if (upperConfirm == true) {\n                // Include Uppercase character set\n                characterTypes += Uppercase;\n            }\n            // console.log(characterTypes);\n\n            var lowerConfirm = window.confirm(\"Do you want to include Lowercase characters?\");\n            // Check if selection has been made\n            if (typeof lowerConfirm == \"boolean\") {\n                if (lowerConfirm == true) {\n                    // Include Lowercase character set\n                    characterTypes += Lowercase;\n                }\n                // console.log(characterTypes);\n\n                var numericConfirm = window.confirm(\"Do you want to include numeric characters?\");\n                // Check if selection has been made\n                if (typeof numericConfirm == \"boolean\") {\n                    if (numericConfirm == true) {\n                        // Include Numeric character set\n                        characterTypes += Numeric;\n                    }\n                    // console.log(characterTypes);\n\n                    var specialcharConfirm = window.confirm(\"Do you want to include special characters?\");\n                    // Check if selection has been made\n                    if (typeof specialcharConfirm == \"boolean\") {\n                        if (specialcharConfirm == true) {\n                            // Include Special character set\n                            characterTypes += Specialchar;\n                        }\n                        // console.log(characterTypes);\n\n                        if (characterTypes.length == 0) {\n                            // If none are selected, alert and loop back\n                            window.alert(\"At least one character type must be chosen.\");\n                            charDialog();\n                        }\n                    }\n                }\n            }\n        }\n    } else {\n        // If out of range, alert and loop back\n        window.alert(\"Number of length needs to be between 8-128\");\n        setPasswordLength();\n        charDialog();\n    }\n};\n\n// Run the function\ncharDialog();\n\nvar password = document.getElementById(\"password\");\n\n// Generate a password using the selected criteria each time button is pressed\nfunction createPassword() {\n    // Declare password as an empty string\n    let password = \"\";\n\n    // Add characters to password from characterTypes until passwordLength is reached\n    for (let i = 0, j = characterTypes.length; i < passwordLength; i++) {\n        password += characterTypes.charAt(Math.floor(Math.random() * j));\n    };\n    // console.log(password);\n\n    document.getElementById(\"password\").value = password;\n};\n\n\n\n// LINES BELOW ARE FOR UIBUILDER AND NODE-RED\nvar config = {};\nfunction setConfig() {\n    config = JSON.parse(document.getElementById('msg').innerText);\n    if (config.passwordLength >= 8 && config.passwordLength <= 128) {\n        passwordLength = config.passwordLength;\n        characterTypes = \"\";\n        if (typeof config.uppercase == \"boolean\") {\n            if (config.uppercase == true) {\n                characterTypes += Uppercase;\n            };\n        } else {\n            uibuilder.send({ \"error\": \"msg.payload.uppercase must be a boolean.\" });\n        };\n        if (typeof config.lowercase == \"boolean\") {\n            if (config.lowercase == true) {\n                characterTypes += Lowercase;\n            };\n        } else {\n            uibuilder.send({ \"error\": \"msg.payload.lowercase must be a boolean.\" });\n        };\n        if (typeof config.numeric == \"boolean\") {\n            if (config.numeric == true) {\n                characterTypes += Numeric;\n            };\n        } else {\n            uibuilder.send({ \"error\": \"msg.payload.numeric must be a boolean.\" });\n        };\n        if (typeof config.special == \"boolean\") {\n            if (config.special == true) {\n                characterTypes += Specialchar;\n            };\n        } else {\n            uibuilder.send({ \"error\": \"msg.payload.special must be a boolean.\" });\n        };\n        if (characterTypes.length == 0) {\n            uibuilder.send({ \"error\": \"At least one of msg.payload.uppercase, msg.payload.lowercase, msg.payload.numeric, msg.payload.special must be true.\" });\n        };\n    } else {\n        uibuilder.send({ \"error\": \"msg.payload.length must be a number between 8-128.\" });\n    };\n};\n\n// Return formatted HTML version of JSON object\nwindow.msgGrabber = function (json) {\n    json = JSON.stringify(json, undefined, 4)\n    json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n    json = json.replace(/(\"(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(\\s*:)?|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)/g, function (match) {\n        var cls = 'number'\n        if ((/^\"/).test(match)) {\n            if ((/:$/).test(match)) {\n                cls = 'key'\n            } else {\n                cls = 'string'\n            }\n        } else if ((/true|false/).test(match)) {\n            cls = 'boolean'\n        } else if ((/null/).test(match)) {\n            cls = 'null'\n        }\n        return '<span class=\"' + cls + '\">' + match + '</span>'\n    })\n    return json\n} // --- End of msgGrabber --- //\n\n// Send a message back to Node-RED\nwindow.fnSendToNR = function fnSendToNR(payload) {\n    uibuilder.send({\n        'topic': 'msg-from-uibuilder-front-end',\n        'payload': document.getElementById(\"password\").value,\n        'config': config,\n    })\n}\n\n// Run this function when the document is loaded\nwindow.onload = function () {\n    // Start up uibuilder - see the docs for the optional parameters\n    uibuilder.start()\n\n    // Listen for incoming messages from Node-RED\n    uibuilder.onChange('msg', function (msg) {\n        console.info('[indexjs:uibuilder.onChange] msg received from Node-RED server:', msg)\n\n        // Dump the msg as text to the \"msg\" html element\n        const eMsg = document.getElementById('msg')\n        eMsg.innerHTML = window.msgGrabber(msg.payload)\n\n        setConfig();\n        createPassword();\n\n        // Pass msg.payload's received through node\n        uibuilder.send({\n            'topic': 'msg-from-uibuilder-passthrough',\n            'config': config,\n            'payload': document.getElementById(\"password\").value,\n        })\n    })\n}","x":430,"y":80,"wires":[]},{"id":"3ce56b19059481db","type":"comment","z":"86a82b7c66374659","name":"index.html","info":"<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\" />\n    <title>Password Generator</title>\n    <link rel=\"stylesheet\" href=\"index.css\" />\n</head>\n\n<body>\n    <div class=\"wrapper\">\n        <header>\n            <h1>Password Generator</h1>\n        </header>\n        <div class=\"card\">\n            <div class=\"card-header\">\n                <h2>Generate a Password</h2>\n            </div>\n            <div class=\"card-body\">\n                <textarea\n            readonly\n            id=\"password\"\n            placeholder=\"Your Secure Password\"\n            aria-label=\"Generated Password\"\n          ></textarea>\n            </div>\n            <div class=\"card-footer\">\n                <button id=\"generate\" class=\"btn\" onclick=\"createPassword(passwordLength, characterTypes)\">Generate Password</button>\n                <button class=\"btn\" onclick=\"fnSendToNR('A message from the sharp end!')\">Send a msg back to Node-RED</button>\n            </div>\n            <div class=\"alt-input\">\n                <h3>Config</h3>\n            <pre id=\"msg\" class=\"msg-grabber\">Waiting for input from Node-RED</pre>\n            </div>\n        </div>\n    </div>\n    <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / -->\n    <script src=\"../uibuilder/vendor/socket.io/socket.io.js\">\n        /* REQUIRED: Socket.IO is loaded only once for all instances. Without this, you don't get a websocket connection */\n    </script>\n    <script src=\"./uibuilderfe.min.js\">\n        /* REQUIRED: remove 'min.' to use dev version */\n    </script>\n    <script src=\"index.js\"></script>\n</body>\n\n</html>","x":300,"y":80,"wires":[]},{"id":"cec9f040febda7bb","type":"comment","z":"86a82b7c66374659","name":"index.css","info":"*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\nhtml,\nbody,\n.wrapper {\n  height: 100%;\n  margin: 0;\n  padding: 0;\n}\n\nbody {\n  font-family: sans-serif;\n  background-color: #f9fbfd;\n}\n\n.wrapper {\n  padding-top: 30px;\n  padding-left: 20px;\n  padding-right: 20px;\n}\n\nheader {\n  text-align: center;\n  padding: 20px;\n  padding-top: 0px;\n  color: hsl(206, 17%, 28%);\n}\n\n.card {\n  background-color: hsl(0, 0%, 100%);\n  border-radius: 5px;\n  border-width: 1px;\n  box-shadow: rgba(0, 0, 0, 0.15) 0px 2px 8px 0px;\n  color: hsl(206, 17%, 28%);\n  font-size: 18px;\n  margin: 0 auto;\n  max-width: 800px;\n  padding: 30px 40px;\n}\n\n.card-header::after {\n  content: \" \";\n  display: block;\n  width: 100%;\n  background: #e7e9eb;\n  height: 2px;\n}\n\n.card-body {\n  min-height: 100px;\n}\n\n.card-footer {\n  text-align: center;\n}\n\n.card-footer::before {\n  content: \" \";\n  display: block;\n  width: 100%;\n  background: #e7e9eb;\n  height: 2px;\n}\n\n.card-footer::after {\n  content: \" \";\n  display: block;\n  clear: both;\n}\n\n.btn {\n  border: none;\n  background-color: hsl(360, 91%, 36%);\n  border-radius: 25px;\n  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 6px 0px rgba(0, 0, 0, 0.2) 0px 1px 1px\n    0px;\n  color: hsl(0, 0%, 100%);\n  display: inline-block;\n  font-size: 22px;\n  line-height: 22px;\n  margin: 16px 16px 16px 20px;\n  padding: 14px 34px;\n  text-align: center;\n  cursor: pointer;\n}\n\nbutton[disabled] {\n  cursor: default;\n  background: #c0c7cf;\n}\n\n.float-right {\n  float: right;\n}\n\n#password {\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  display: block;\n  width: 100%;\n  padding-top: 15px;\n  padding-left: 15px;\n  padding-right: 15px;\n  padding-bottom: 85px;\n  font-size: 1.2rem;\n  text-align: center;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  border: 2px dashed #c0c7cf;\n  border-radius: 6px;\n  resize: none;\n  overflow: hidden;\n}\n\n@media (max-width: 690px) {\n  .btn {\n    font-size: 1rem;\n    margin: 16px 0px 0px 0px;\n    padding: 10px 15px;\n  }\n\n  #password {\n    font-size: 1rem;\n  }\n}\n\n@media (max-width: 500px) {\n  .btn {\n    font-size: 0.8rem;\n  }\n}","x":560,"y":80,"wires":[]},{"id":"ec22946b3b5c948d","type":"inject","z":"86a82b7c66374659","name":"8 Numeric","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"passwordLength\":8, \"uppercase\":false, \"lowercase\":false, \"numeric\":true, \"special\":false}","payloadType":"json","x":120,"y":240,"wires":[["632f590dbee6c4ca"]]},{"id":"1caac48360d18d6c","type":"inject","z":"86a82b7c66374659","name":"8 Special","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"passwordLength\":8, \"uppercase\":false, \"lowercase\":false, \"numeric\":false, \"special\":true}","payloadType":"json","x":120,"y":280,"wires":[["632f590dbee6c4ca"]]},{"id":"869012f53baf8e02","type":"inject","z":"86a82b7c66374659","name":"8 Upper","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"passwordLength\":8, \"uppercase\":true, \"lowercase\":false, \"numeric\":false, \"special\":false}","payloadType":"json","x":130,"y":160,"wires":[["632f590dbee6c4ca"]]},{"id":"3630108e698f7c2b","type":"inject","z":"86a82b7c66374659","name":"8 none","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"passwordLength\":8, \"uppercase\":false, \"lowercase\":false, \"numeric\":false, \"special\":false}","payloadType":"json","x":130,"y":320,"wires":[["632f590dbee6c4ca"]]},{"id":"279cda872a7db8d4","type":"switch","z":"86a82b7c66374659","name":"","property":"error","propertyType":"msg","rules":[{"t":"nempty"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":430,"y":180,"wires":[["e191a10c4b08a0b8"],["b6c72648ca774348"]]},{"id":"e191a10c4b08a0b8","type":"function","z":"86a82b7c66374659","name":"display errors","func":"node.error(msg.error);","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1060,"y":160,"wires":[]},{"id":"7d7da6797b4d10f9","type":"switch","z":"86a82b7c66374659","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"msg-from-uibuilder-front-end","vt":"str"},{"t":"eq","v":"msg-from-uibuilder-passthrough","vt":"str"}],"checkall":"false","repair":false,"outputs":2,"x":790,"y":220,"wires":[["c215fb7168aec76f"],["9ed1645eb88528ca"]]},{"id":"dfd8ac18f7a4c26f","type":"debug","z":"86a82b7c66374659","name":"data from passthrough","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1080,"y":240,"wires":[]},{"id":"d478513ca2c3fae5","type":"inject","z":"86a82b7c66374659","name":"20 All","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"passwordLength\":20, \"uppercase\":true, \"lowercase\":true, \"numeric\":true, \"special\":true}","payloadType":"json","x":130,"y":360,"wires":[["632f590dbee6c4ca"]]},{"id":"3442fd889d1c3d80","type":"comment","z":"86a82b7c66374659","name":"Input format","info":"{\n    \"passwordLength\": Number,\n    \"uppercase\": Boolean,\n    \"lowercase\": Boolean,\n    \"numeric\": Boolean,\n    \"special\": Boolean\n}","x":110,"y":80,"wires":[]},{"id":"9ed1645eb88528ca","type":"switch","z":"86a82b7c66374659","name":"","property":"config.passwordLength","propertyType":"msg","rules":[{"t":"btwn","v":"8","vt":"num","v2":"128","v2t":"num"}],"checkall":"true","repair":false,"outputs":1,"x":910,"y":240,"wires":[["dfd8ac18f7a4c26f"]]},{"id":"c71b2b2f617441eb","type":"inject","z":"86a82b7c66374659","name":"1 All FAIL","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"passwordLength\":1, \"uppercase\":true, \"lowercase\":true, \"numeric\":true, \"special\":true}","payloadType":"json","x":120,"y":440,"wires":[["632f590dbee6c4ca"]]},{"id":"4774ae2044f1675f","type":"inject","z":"86a82b7c66374659","name":"test","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"passwordLength\":8, \"uppercase\":\"test\", \"lowercase\":\"test\", \"numeric\":\"test\", \"special\":\"test\"}","payloadType":"json","x":130,"y":400,"wires":[["632f590dbee6c4ca"]]},{"id":"442d06f259ed2971","type":"inject","z":"86a82b7c66374659","name":"8 Lower","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"passwordLength\":8, \"uppercase\":false, \"lowercase\":true, \"numeric\":false, \"special\":false}","payloadType":"json","x":130,"y":200,"wires":[["632f590dbee6c4ca"]]},{"id":"1b9ac379c815df9e","type":"comment","z":"86a82b7c66374659","name":"Deploy, copy index files, deploy again, open page","info":"","x":440,"y":300,"wires":[]}]

And allowing messages to change content of the page.

I'm afraid index.html is missing

Edited, should have the code in the comment nodes above.

1 Like

As it says in the wiki article, that example was written for uib v1 and updated for v2. We are now on v5 and a lot has changed since then. Unfortunately I don't have time to update all of the old examples myself and I don't use frameworks like moon myself anyway. So unless other people step up and update the articles, unfortunately you need to compare against the current templates and check for any breaking changes in newer versions of moon as well.

Did you try A first-timers walkthough (totallyinformation.github.io) or Creating data-driven web apps (totallyinformation.github.io)?

thank you all for the input - i will give these suggestions a try.