We have a number of applications where we have an input field that the operators scan barcodes to fill the field.
We needed a way for the field to be autofocused when entering the step so the scanner result would load into the field.
We built a custom input widget which steals input focus when the step loads. Hope this helps others! Please share your improvements.
To use:
- Copy the below JSON into a file called autofocus.json
- From your tulip custom widgets dashboard, click the 3dots next to the “Create Custom Widget” button
- Choose Import
- Select the file “autofocus.json”
- Pull the widget into an app
- Configure triggers
{"version":1,"customWidget":{"_id":"JSHxLBN7miP3yz3st","name":"AutoFocus Text Input - v2 with events","createdBy":"ptzDY4QKn5TidGijP","createdAt":1750265014379,"updatedBy":"ptzDY4QKn5TidGijP","updatedAt":1750335915538,"props":[{"id":"RYEgLxX5xGhmWDhQf","name":"Value","description":"type=text, readonly. \nConnect to the Variable or Table Record field where you want to store the input","requireWriteable":true,"type":"string"},{"id":"EmRZckY4bsW6zZGcM","name":"Label","description":"type = text, readonly\nEnter the text that you want to display as the label. Can be connected to a dynamic data source like Variable or Table Record.","requireWriteable":false,"type":"string"},{"id":"kbchqDRKQ8K7o67jc","name":"HelperText","description":"type = text, readonly\nEnter the text that will be shown between the label and the input to give more guidance to the user","requireWriteable":false,"type":"string"},{"id":"kFYH7e5Y2mxfaBKye","name":"LabelFontSize","description":"type = integer, readonly\nFont size of the Label","requireWriteable":false,"type":"integer"},{"id":"MhSXKnc68zKcPto3p","name":"InputFontSize","description":"type = integer, readonly\n Font size of the input text box","requireWriteable":false,"type":"integer"},{"id":"SHJnQ2TH3ddscoDRx","name":"LabelColor","description":"type = color, readonly\nAllows you to set the label text color","requireWriteable":false,"type":"color"},{"id":"aSqw59z7k8MopM7re","name":"TextColor","description":"type = color, readonly\nAllows you to set the input text color","requireWriteable":false,"type":"color"}],"events":[{"id":"owDnuwpvJaLe46b6x","name":"input is exited","description":"","type":"string"},{"id":"RkpZPqDnrgYfXbh7i","name":"enter key is pressed","description":"","type":"string"}],"persistentId":"Tx2FtC9fABDf849zp","javascript":"const container = document.getElementById(\"container\");\nconst label = document.getElementById(\"label\");\nconst input = document.getElementById(\"text\");\nconst helper = document.getElementById(\"helper\");\n\ninput.focus();\n\ninput.addEventListener(\"blur\", () => {\n fireEvent(\"input is exited\", input.value);\n});\n\ninput.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\") {\n fireEvent(\"enter key is pressed\", input.value);\n }\n});\n\ngetValue(\"Value\", (data) => {\n input.value = data == null ? \"\" : data;\n});\n\ngetValue(\"Label\", (lbl) => {\n label.innerHTML = lbl == null ? \"My Label\" : lbl;\n});\n\ngetValue(\"HelperText\", (ht) => {\n helper.innerHTML = ht == null ? \"\" : ht;\n});\n\ngetValue(\"LabelFontSize\", (size) => {\n label.style.fontSize = size == null ? \"32px\" : `${size}px`;\n});\n\ngetValue(\"InputFontSize\", (size) => {\n input.style.fontSize = size == null ? \"40px\" : `${size}px`;\n});\n\ngetValue(\"TextColor\", (tclr) => {\n input.style.color = tclr == null ? \"#121C2E\" : tclr;\n});\n\ngetValue(\"LabelColor\", (lclr) => {\n label.style.color = lclr == null ? \"#121C2E\" : lclr;\n helper.style.color = lclr == null ? \"#121C2E\" : lclr;\n});\n\n// Event to Save the value\ninput.addEventListener(\"input\", () => {\n setValue(\"Value\", input.value);\n});\n","css":"body {\n background-color: white;\n}\n\nbody {\n background-color: white;\n}\n\nbody {\n background-color: rgba(0, 0, 0, 0);\n width: 100vw;\n height: 100vh;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\",\n \"Noto Sans\", \"Ubuntu\", \"Droid Sans\", \"Helvetica Neue\", \"sans-serif\";\n}\n\n.container {\n width: auto;\n height: auto;\n padding: 10px;\n}\n\n.label {\n display: inline-block; /* add this */\n font-size: 32px;\n padding-bottom: 10px;\n font-weight: bold;\n}\n.helper {\n display: inline-block; /* add this */\n padding-bottom: 10px;\n font-size: 28px;\n font-style: italic;\n}\n\ninput[type=\"text\"],\n[type=\"email\"],\n[type=\"tel\"],\n[type=\"password\"],\n[type=\"search\"],\n[type=\"url\"] {\n width: 98%;\n font-size: 40px;\n}\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"month\"],\ninput[type=\"datetime-local\"] {\n width: 98%;\n}\n\ninput:invalid {\n border: 2px dashed red;\n box-shadow: 0 0 5px 1px red;\n}\n\ninput:focus:invalid {\n box-shadow: none;\n}\n\ninput:valid {\n border: 1px solid grey;\n}\n","html":"<div id=\"container\" class=\"container\">\n <label id=\"label\" class=\"label\"></label><br>\n <span id=\"helper\" class=\"helper\"></span>\n <input id=\"text\" type=\"text\"></input>\n</div>","defaultHeight":150,"defaultWidth":350,"description":"A text input with a label and helper text","icon":"list","permissions":[],"thirdPartyLibraries":[]}}