Form validation with HTML5
As a day-to-day React developer, when it comes to solving complex UI problems, such as form validation, my first instinct would be to use straight up JavaScript. Depending on the criteria, field values can be validated on the inputâs onchange
event or the formâs onsubmit
event. You would store some regex and/or maximum characters. Then, when you need to validate it, youâd need to run the inputsâ value properties against these.
However, I recently found that HTMLâs own <input>
can take its own pattern
attribute. This attribute takes a regex (namely of the JavaScript flavour) and matches the input to the pattern. The pattern of the below input looks for an input with all-capital text:
<label for='scream-content'>Enter something to scream:</label>
<input id='scream-content' type='text' pattern='[A-Z]+'/>
Here is a codepen if you want to poke around:
Here, if the user enters an invalid pattern (i.e. one with lower-case letters), the UI would to show that the input is invalid. In the above plain HTML example, different browsers would handle this differently (wonât cover how, but open this Codepen in other browsers and have a look). It was easy to just add a couple extra attributes to make sure the user fills in the form correctly: title
gives the user a description of the requested pattern; required
makes sure the user doesnât submit the form without entering a value. The form also avoids sending the data to the server when the entire form is invalid.
And with that, we have our first taste of a fully HTML5 form complete with validation. We can verify this by disabling JavaScript when visiting that page. It still guides the user how to successfully submit the form.
But then letâs say you want to streamline designs between browsers. In a real-world scenario, a company might want to fine tune their own journey with custom details.
In this case, we would reach into the HTML5 formâs APIs with JavaScript.
In the JavaScript first tell the <form>
element that we donât need it to handle validation by giving it a novalidate
attribute. Instead, we will manually intercept the formâs onsubmit
event with an EventListener.
I learned here that the formElement
interface actually has some helpful methods to do with formValidation. (See them here) Here weâll use the elements
method to get access to all its elements, then on each one, we check their validity with the validity
property.
As an aside, the validity property is really powerful as it returns a whole Validity State of the input element. This is useful if you need to specify the error that is actually happening. E.g. whether the field is required but empty, whether the field currently has an invalid value, or even if the value is too long or too short!
Some logic is added to remove the error class if the field is actually valid and to check if a previously invalid field is still invalid (in which case, just leave it). The loop is directed to continue
after the element is dealt with so validation can resume on the rest of the elements.
By adding the error class to the input, we can streamline designs between different browsers, for example by adding a solid red border to invalid fields, rather than just rely on the in-built browser behaviour.
Whatâs cool about this form is that if JavaScript is disabled or fails to load, the form validation will continue to work. This is why I decided to add the novalidate attribute with JavaScript rather than directly in the HTML.