HTML5 Form Validation
Client Side Form Validation
When a user submits a form, we generally want to send the form's data to a server.
We use the form's action to specify a server URL, and a method to indicate the
HTTP request type to use when sending the data.
Before we can use this data in a meaningful way, we need to validate it. It's easy for users to make typos, enter the right information but in the wrong field, or use a format we aren't expecting. We need to be able to parse and understand the data using code. This means having data that follows some rules.
In order to be able to work with user data, we have to provide some mechanisms for enforcing these rules, and give users hints, guides, and safety checks as they are entering data and submitting forms.
We have two opportunities to validate form data:
- Client-Side: before we submit the form to the server, we validate it in the browser using HTML5 and JavaScript.
- Server-Side: after the data is submitted, the server must re-validate it.
We will be focusing on client-side validation in this course.
You might be wondering why we bother validating form data twice, if we're just going to re-validate it no matter what on the server. There are a number of reasons:
- Save bandwidth: don't send data over the network if it's incomplete or not in the correct form
- Immediate feedback: users don't have to wait for their data to travel all the way to the server, and the page to reload, before getting feedback that they need to correct something simple.
- Contextual feedback: prompt users to correct mistakes as they are entering the data vs. at the end, after they've moved on from entering some piece of information (e.g. a credit card).
HTML5 Validation Features
We've already discussed a number of important <input> types that allow us to
tell the browser about the type of data we expect, for example <input type="tel"> for telephone numbers
or <input type="email">
for email addresses.
Each of these special purpose <input> types comes with its own set of built-in data validation:
Email Address
An email address must not be an empty string, and must be a valid (i.e., text is in valid email format vs. email address actually exists). If you include the multiple attribute, the control will allow a list of addresses, and validate each one.
Telephone Number
Phone numbers are very difficult to validate, because they differ so much around the world.
You might think you could just check for something like 555-555-5555, but this would miss
things like country codes, number patterns that use a different number of digits, short-codes
for texting, 1-800 style numbers, etc.
As a result, there is no default validation applied to a tel type input.
URL
Unlike telephone numbers, URLs can be validated. If you use a url type input, the browser
will make sure it is not empty, and that the value is a valid URL.
Dates and Times
<input type="date">, <input type="time">, <input type="week">, <input type="month">, <input type="date-local">
Dates and times are not validated by the browser. However, the user will usually be prompted
to "pick" a date/time value visually instead of entering one as text. You can also further
restrict the date/time by adding a min="..." or max="..." to the input, which
specifies a date/time to use as a lower or upper range when validating.
Colour
A color's value is considered to be invalid if it can't be converted (by the browser) into a
seven-character lower-case hexadecimal value (e.g., #000000).
Number
<input type="number">, <input type="range">
A number must be a valid number, or the browser won't allow it. You can also further
restrict the number's value by adding a min="..." or max="..." to the input, which
specifies a lower or upper range when validating.
Using Attributes to Prevent Invalid Data
Beyond choosing trying to choose the most appropriate <input> type for your data,
another layer of client-side validation comes from using attributes to indicate
to both the user and browser what we expect to be entered.
placeholder and title
We've discussed placeholder previously as part of our forms and CSS discussion. It's important to highlight it once again
since it also plays an important role in helping the user understand how to enter
data properly.
Together with <label>s and the title attribute (shown when you hover over
an element in a tooltip), these extra bits of text provide important clues and
instructions about how to use a given input control.
For example, if we are expecting the user to enter a list of email addresses, we could do the following:
<label for="address-list">Email Address List</label>
<input
id="address-list"
type="email"
multiple
placeholder="name1@example.com, name2@example.com, ..."
title="List of email addresses, separated by commas"
/>
disabled
The disabled attribute
is a boolean (i.e., it is present or not present) that indicates that a field cannot
be interacted with by the user. In the browser it will show up with a dimmer colour,
and clicking it will have no effect.
We can use disabled to turn off certain controls in a form that don't currently apply.
Sometimes a form will have options with dependencies on other controls. For example,
booking a flight that is one-way vs. two-way and whether or not you
need a second date entered for the return trip.
<form action="/s" name="login">
<input type="text" name="flight" />
<input type="date" name="date1" />
<input type="checkbox" name="return-flight" />
<input type="date" value="date2" disabled />
</form>
Using disabled allows us to include and display optional input options in a form
without polluting the data by accidentally allowing the user to enter information
that isn't appropriate.
required
The required attribute is a boolean (i.e., it is present or not present) that indicates
that a field must have a value before the user can submit the form. The browser
will block attempts to submit until a value has been entered.
<form action="/s" name="login">
<input type="text" name="username" required />
<input type="password" name="password" required />
<input type="submit" value="Login" />
</form>
In the form above, both the username and password fields are required, and must
have a value before the form can be submitted (i..e, by clicking the Login button).
Notice that the submit control does not have required attribute.
When a field has the required attribute, the browser automatically applies the :required
pseudo-class. On the other hand, any field without the required attribute automatically
gets the :optional pseudo-class applied. This can be useful in CSS styling.
input:required {
/* styles for required input controls */
}
input:optional {
/* styles for optional input controls */
}
pattern
The pattern attribute
allows us to include a regular expression for the browser to use when validating
the value entered by a user for a given input control.
For example, imagine if we need the user to enter a file extension and want to support
data of the following form .exe, .EXE, or exe.:
<input name="file-extension" type="text" placeholder=".exe" pattern="\.?[a-zA-Z]{3}" />
Consider how you might write a regular expression for each of the following:
- social security number (###-##-####)
- phone number (555-555-5555 or 555-5555 or (555) 555-555)
- ip address (127.0.0.1 or 255.255.255.255)
- username (alpha, numbers underscore, dash, 8-16 long)
- password (alpha, number, symbols, underscore, dash, up to 256 long)
- postal code (m5w 1e6 or M5W 1E6 or M5W1E6)
- price ($1.50 or 1.50 or 1)
- seneca course code (ABC123SSA)