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 = e.target.innerHTML\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.