How to create a number panel that is able to input a 7 digit number

Hey everyone i am a student and the company i have an internship in introduced me to node red. all of this is new to me and i feel kinda stuck haha, especially because none of my dev friends even heard about this so i had almost no one to share his wisdom with me.

anyway I feel that i kinda got the basics but i couldn't figure out a couple of things.

so basically i want to create a number panel (0 to 9) that is able to input a 7 digit number in the format of XX - XXXXX also id like a button to delete the inputs one by one for example 75-45467 becomes 75-4546
and a button to save the number into a table, or something of that sort
if you guys can help me with a link or something. that would be much appreciated.
and thank you in advance :saluting_face: :saluting_face:

Welcome to the forums @MoonAngel
can I assume you are referring to the use of the Dashboard Node features?

see here:
node-red-dashboard (node) - Node-RED (

kinda but not really my supervisor wants me to create a panel that you can interact with in the dashboard itself
and thank you for the fast reply good sir @marcus-j-davies


I have moved this post to the Dashboard category, I am not a pro with dashboard myself - but plenty who are.

1 Like

yes sir thank you so much

There are lots of examples on the forum that you can use to build from. Search in the Dashboard category.

for example, you could use this: Adding `output` function to buttons designed in `template` node - #65 by Steve-Mcl feed the value to a join node set to length 7.

1 Like

Can you use a ui_form node with a text input field?

1 Like

i will check these tomorrow since its late rn haha :saluting_face: thank you sir

which panel should i download to find this by the way i found the ui_control but no ui form node

ui_form is one of the node-red-dashboard nodes.

1 Like


i was able to create the panel and i actually made some progress

everything works just fine except for one thing
when i press the edit button i want to replace the toggled item with the value that is in the text input(in this case i want to be able to replace Sn 12-36512 with Sn 12-22222 when i press the edit button nothing happens
this is the current Flow

and this is the editCheckedItem code

function editCheckedItem(msg) {
    const { checkedIndex, unformattedNumber } = msg.payload;

    if (checkedIndex === undefined || unformattedNumber === undefined) {
        console.error("Missing data for editing:", msg.payload);
        return; // Or handle the error differently

    // Get the template's generated DOM content
    const templateContent = node.get('msg').payload.$content;

    // Find the checkbox element based on its index (adjust selector as needed)
    const checkboxElement = templateContent.querySelectorAll('input[type="checkbox"]:nth-child(2)')[checkedIndex];

    if (checkboxElement) {
        // Directly set the checked value using the unformatted number
        checkboxElement.checked = unformattedNumber; // Use unformattedNumber here
    } else {
        console.error("Invalid checkbox index:", checkedIndex); // Or handle the error differently

once again i am stuck lol

A bit confusing but ..
Are you trying to send some existing Sn code to the dashboard so you can edit it and then store after editing is complete?

i have a number panel that can input 7 digits
for example if i type out 1234567
the text input shows Sn 12-34567 when i press confirm the value gets added to a table
then i just input a different 7 digit number lets say for example Sn 11-11111 (after being in the correct form)
(thats the format of my company devices serial number i guess?)
i just want my edit button to replace the toggled value with the current value in the text input
by deleting the toggled item and adding the new number in the table

I see you have tried hard.
But isn't it more clever to validate input from that pin pad to have always correctly formatted serial number in hands?

I have an example for you prepared ..

[{"id":"f6a3dd5921436153","type":"ui_template","z":"f8b8c963bdc117f5","group":"07ca9eabfe300b52","name":"pinpad","order":2,"width":"4","height":"5","format":"<div class=\"serialNumber-widget\">\n    <div class=\"serialNumbertext\">{{serialNumber}}</div>\n    <div class=\"serialNumberpad\">\n        <div ng-click=\"serialNumberClick($event)\">1</div>\n        <div ng-click=\"serialNumberClick($event)\">2</div>\n        <div ng-click=\"serialNumberClick($event)\">3</div>\n        <div ng-click=\"serialNumberClick($event)\">4</div>\n        <div ng-click=\"serialNumberClick($event)\">5</div>\n        <div ng-click=\"serialNumberClick($event)\">6</div>\n        <div ng-click=\"serialNumberClick($event)\">7</div>\n        <div ng-click=\"serialNumberClick($event)\">8</div>\n        <div ng-click=\"serialNumberClick($event)\">9</div>\n        <div ng-click=\"serialNumberClick($event)\" class=\"control\">CLR</div>\n        <div ng-click=\"serialNumberClick($event)\">0</div>\n        <div ng-click=\"serialNumberClick($event)\" class=\"control\">🡄</div>\n    </div>\n    <div class=\"submit\" ng-click=\"submitSerialNumber()\">\n        SUBMIT\n    </div>\n<div>\n<style>\n    .serialNumberpad-container{\n        position:relative;\n        display:flex;\n        align-content: center;\n        flex-direction: row;\n        flex-wrap: wrap;\n        justify-content: center;\n    }\n    .serialNumber-widget{\n        width: 100%;\n        height: 100%;\n        display:grid;\n        gap:4px;\n        grid-template-rows:1fr 4fr 1fr;\n    }\n    .serialNumbertext{        \n        display: flex;\n        flex-direction: row;\n        align-items: center;\n        justify-content: flex-end;\n        font-size: large;\n        font-weight: 600;\n        min-height:1em;\n        padding-inline: 0.5em;\n        background: #a9a9a920;\n    }\n    .serialNumberpad{\n        display:grid;\n        grid-template-columns: 1fr 1fr 1fr;\n        gap: 4px;\n        width: 100%;\n        height: 100%;\n        cursor:auto;\n    }\n    .serialNumberpad div, .submit{\n        background:green;\n        display: flex;\n        flex-direction: row;\n        align-items: center;\n        justify-content: center;\n        font-size: large;\n        font-weight: 600;\n        user-select:none;\n        cursor:pointer;\n    }\n    .serialNumberpad div.control{\n        background:cornflowerblue;        \n    }\n    .submit{\n        background:palevioletred;\n        font-size: medium;\n        font-weight: 500;\n    }\n    \n</style>\n<script>\n(function(scope) {\n\n    scope.serialNumber = \"\"   \n    const delimiters = [{char:\"S\", pos:0},{char:\"n\", pos:1},{char:\" \", pos:2},{char:\"-\", pos:5}]\n    const length = 7 + delimiters.length\n\n    function clearSerialNumber(){\n        scope.serialNumber = \"\"\n        //scope.send({payload:scope.serialNumber,topic:'serialNumberpad-submit'})\n    }\n\n    function removeLast(){\n        // it does remove last but also delimitters when needed.\n        let count = -1      \n        delimiters.forEach(delimiter => {\n            if(scope.serialNumber.endsWith(delimiter.char)){\n                count = (delimiter.char.length + 1) * -1            \n            }            \n        })\n        scope.serialNumber = scope.serialNumber.slice(0, count)            \n    }    \n\n    function checkSerialNumber(){\n        // it must have correct length    \n        return scope.serialNumber.length == length\n    }\n\n    function updateSerialNumber(v){\n        if(checkSerialNumber()){\n            //if it has correct length, dont add more\n            return\n        }\n        // chek if next character needs to be delimiter, if so, it will be added\n        scope.serialNumber = checkDelimiters(scope.serialNumber)\n        // add input from key pad\n        scope.serialNumber = scope.serialNumber.concat(v)\n        // chek again for delimitters        \n        scope.serialNumber = checkDelimiters(scope.serialNumber)\n    }\n\n    function checkDelimiters(s){\n        // check if it is neede to add some of delimitters\n        delimiters.forEach(delimiter => {\n            if(s.length == delimiter.pos){\n                s = s.concat(delimiter.char)\n            }\n        })        \n        return s\n    }\n\n   \n\n    scope.serialNumberClick = function(e){\n        // input from key pad elements\n        let v =\n        if(v == \"CLR\"){\n            clearSerialNumber()\n        }\n        else if(v == \"🡄\"){\n            removeLast()\n        }\n        else{\n            updateSerialNumber(v)\n            \n        }        \n    }\n    scope.submitSerialNumber = function(){\n        if(!checkSerialNumber()){\n            //don't send if the number is not complete            \n            return\n        }       \n        scope.send({payload:scope.serialNumber,topic:'serialNumberpad-submit'})\n    }\n    \n\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":false,"resendOnRefresh":true,"templateScope":"local","className":"pinpad-container","x":490,"y":380,"wires":[["354adbba6efd0aa1"]]},{"id":"354adbba6efd0aa1","type":"debug","z":"f8b8c963bdc117f5","name":"SERIAL","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":640,"y":380,"wires":[]},{"id":"07ca9eabfe300b52","type":"ui_group","name":"Pinpad","tab":"62083694d0eab7ca","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"62083694d0eab7ca","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

It doesn't take any input (it's for you to add and figure out what to do with the input then) but happily creates correctly formatted string when you use the keypad.

1 Like

the thing is different devices have different serial number so if a Tech wants to change a device i want him to be able to replace the old s number with the new one. that is why

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