Custom node - property validation isn't reflected in the editor UI

Hello, I'm having an issue with my property validation when setting up the editor UI. My invalid input does not have a red border around it and the code I set up to toggle a validation message for the URL field does not run. Inside my node HTML I have this:

<script type="text/html" data-template-name="custom-node">
<div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
        <input type="text" id="node-input-name" placeholder="Name" />
        <input type="hidden" id="node-input-name-type" />
    </div>
    <div class="form-row">
        <label for="node-input-url"><i class="fa fa-globe"></i> URL</label>
        <input type="text" id="node-input-url" placeholder="https://example.com/file.wasm" />
        <input type="hidden" id="node-input-url-type" />
    </div>
    <div class="form-row form-tips" id="node-validation-url" style="display:none;">
        <b>ℹ️</b> This must be a valid URL
    </div>
</script>

I think this is fine as it is at the moment. My oneditprepare function looks like this:

oneditprepare: function () {
            let strs = ["name", "url"];

            /*
             * Set up the input types for strings
             * with optional validation if a message element is present
             */
            const addValidation = (el) => {
                let id = el.id;
                let validationEl = document.getElementById(`node-validation-${id}`);
                if (validationEl) {
                    console.log("Adding validation check for", id);
                    el.on("input", function (event, type, value) {
                        let isValid = el.typedInput("validate");
                        console.log("input ", id, "valid:", isValid);
                        validationEl.style.display = isValid ? "none" : "block";
                    });
                }
            };

            for (let id of strs) {
                let el = $(`#node-input-${id}`).typedInput({
                    type: "str",
                    types: ["str"],
                    typeField: `#node-input-${id}-type`,
                });
                addValidation(el);
            }
}

The validate function for the URL looks like this:

function (v) {
                    //check it is a valid URL.
                    try {
                        let u = new URL(v);
                        console.log(v, "is a valid url", u);
                        return true;
                    } catch (e) {
                        console.log("url NOT valid for", `'${v}'`, e);
                        return false;
                    }
}

The idea is that it's set up to allow for more than just string-typed inputs later on. The questions I have are:

  • Is the typedInput() call inside the for loop the correct way to ensure inputs are typed?
  • Can you see any issues in the addValidation?

The node and properties appear in the interface, but the red border I'm expecting around the URL field never appears. The console.log calls I've added appear for the validate function but not for the input event listeners, but I can't work out why.

Why are you not using the API methods instead of "rolling your own"?

Does it not work setting the validate function in the object entry & then, if needs be, calling the validate function on the typedInput E.G: isValid = $(".input").typedInput('validate');

See here: TypedInput Widget : Node-RED

Property Type Required Description
validate function A function to validate the value for the type.

Apologies for not getting back to you sooner. My solution for the moment has been to hard-code the options into independent nodes, such that each one doesn't need any individual configuration.

The idea behind my original code was to set up a generic, reproducible function that would display/toggle an associated node-validation-X element if the input is invalid, but only if that message exists in the HTML, as well as highlighting the input with the red border. That way I can focus on constructing HTML for new nodes, rather than copy/pasting validation checks. I suspect my event handler is interrupting the default check though so I'll have to take another look at the docs or find a working example on the forum