O'Reilly logo

JavaScript Cookbook by Shelley Powers

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

14.3. Highlighting Form Field with Missing or Incorrect Data

Problem

You want to highlight missing or incorrectly entered information in a form field.

Solution

For the fields that need to be validated, assign a function to the form field’s onchange event handler that checks whether the field value is valid. If the value is invalid, pop up an alert with information about the error, and highlight the field using a contrasting color:

document.getElementById("elemid").onchange=validateField;
...
function validateField() {

  // check for number
  if (isNaN(parseFloat(this.value))) {
     this.parentNode.setAttribute("style",
"background-color: #ffcccc");
     this.setAttribute("aria-invalid", "true");
     generateAlert("You entered an invalid value in Third Field.
Only numeric values such as 105 or 3.54 are allowed");
  }
}

For the fields that need a required value, assign a function to the field’s onblur event handler that checks whether a value has been entered:

document.getElementById("field").onblur=checkMandator;
...
function checkMandatory() {
  // check for data
  if (this.value.length === 0) {
     this.parentNode.setAttribute("style",
"background-color: #ffcccc");
     this.setAttribute("aria-invalid", "true");
     generateAlert("A value is required in this field");
  }
}

If any of the validation checks are performed as part of the form submittal, make sure to cancel the submittal event if the validation fails.

Discussion

You can’t depend on visual indicators to highlight errors, but they can be a useful extra courtesy.

Highlighting an error with color is good, but you should avoid colors that are hard to differentiate from the background. If the form background is white, and you use a dark yellow, gray, red, blue, green, or other color, there’s enough contrast that it doesn’t matter if the person viewing the page is color blind or not. In the example, I used a darker pink around the incorrect field, against a white page.

Using a color highlight for form errors is good, but it isn’t enough: you also need to provide a text description of the error, so there’s no question in the user’s mind about what the problem is.

How you display the information is also an important consideration. None of us really like to use alert boxes, if we can avoid them. Alert boxes can obscure the form, and the only way to access the form element is to dismiss the alert, with its error message. A better approach is to embed the information in the page, near the form. Fortunately, with the new ARIA roles, we can create an alert message and assign it an ARIA role of alert, alerting those using screen readers or other AT devices.

One final touch: to ensure there’s no confusion about which field is invalid, the solution also sets the aria-invalid attribute to true on the field. Not only does this provide useful information for AT device users immediately, it can be used to discover all incorrect fields when the form is submitted.

Example 14-1 demonstrates how to highlight an invalid entry on one of the form elements, and highlight missing data in another. The example also traps the form submit, and checks whether there are any invalid form field flags still set. Only if everything is clears is the form submittal allowed to proceed.

Example 14-1. Providing visual and other cues when validating form fields

<!DOCTYPE html>
<head>
<title>Validating Forms</title>
<style>
[role="alert"]
{
  background-color: #ffcccc;
  font-weight: bold;
  padding: 5px;
  border: 1px dashed #000;
}
div
{
  margin: 10px 0;
  padding: 5px;
  width: 400px;
  background-color: #ffffff;
}
</style>
<script>

window.onload=function() {

  document.getElementById("thirdfield").onchange=validateField;
  document.getElementById("firstfield").onblur=mandatoryField;
  document.getElementById("testform").onsubmit=finalCheck;
}

function removeAlert() {

   var msg = document.getElementById("msg");
   if (msg) {
      document.body.removeChild(msg);
   }
}

function resetField(elem) {
   elem.parentNode.setAttribute("style","background-color: #ffffff");
   var valid = elem.getAttribute("aria-invalid");
   if (valid) elem.removeAttribute("aria-invalid");
}

function badField(elem) {
  elem.parentNode.setAttribute("style", "background-color: #ffeeee");
  elem.setAttribute("aria-invalid","true");
}
function generateAlert(txt) {

   // create new text and div elements and set
   // Aria and class values and id
   var txtNd = document.createTextNode(txt);
   msg = document.createElement("div");
   msg.setAttribute("role","alert");
   msg.setAttribute("id","msg");
   msg.setAttribute("class","alert");

   // append text to div, div to document
   msg.appendChild(txtNd);
   document.body.appendChild(msg);
}

function validateField() {

  // remove any existing alert regardless of value
  removeAlert();

  // check for number
  if (!isNaN(parseFloat(this.value))) {
     resetField(this);
  } else {
     badField(this);
     generateAlert("You entered an invalid value in Third Field.
Only numeric values such as 105 or 3.54 are allowed");
  }
}

function mandatoryField() {

   // remove any existing alert
   removeAlert();

   // check for value
   if (this.value.length > 0) {
     resetField(this);
   } else {
     badField(this);
     generateAlert("You must enter a value into First Field");
   }
}
function finalCheck() {

  removeAlert();

  var fields = document.querySelectorAll("[aria-invalid='true']");
  if (fields.length > 0) {
    generateAlert("You have incorrect fields entries that must be
fixed before you can submit this form");
    return false;
  }
}

</script>
</head>
<body>

<form id="testform">
   <div><label for="firstfield">*First Field:</label><br />
      <input id="firstfield" name="firstfield" type="text"
aria-required="true" /></div>
   <div><label for="secondfield">Second Field:</label><br />
      <input id="secondfield" name="secondfield" type="text" /></div>
   <div><label for="thirdfield">Third Field (numeric):</label><br />
      <input id="thirdfield" name="thirdfield" type="text" /></div>
   <div><label for="fourthfield">Fourth Field:</label><br />
      <input id="fourthfield" name="fourthfield" type="text" /></div>

<input type="submit" value="Send Data" />
</form>

</body>

If either of the validated fields is incorrect in the application, the parent element’s background color is set to pink and an error message is displayed. In addition, the aria-invalid attribute is set to true in the field, and an ARIA role is set to alert on the error message, as shown in Figure 14-1.

Highlighting an incorrect form field

Figure 14-1. Highlighting an incorrect form field

Notice in the code that the element wrapping the targeted form field is set to its “correct state” when the data entered is correct, so that when a field is corrected it doesn’t show up as inaccurate or missing on the next go-round. Regardless of what event happens, I remove the existing message alert, as it’s no longer valid once the event that triggered it has been handled.

When the form is submitted, the application uses a querySelectorAll method call to check for all instances of aria-invalid set to true, and rejects the submission until these are corrected, as shown in Figure 14-2:

var badFields = document.querySelectorAll("[aria-invalid='true']");

You can also disable or even hide the correctly entered form elements, as a way to accentuate those with incorrect or missing data. However, I don’t recommend this approach. Your users may find as they fill in the missing information that their answers in other fields were incorrect. If you make it difficult for them to correct the fields, they’re not going to be happy with the experience—or the company, person, or organization providing the form.

Another approach you can take is to only do validation when the form is submitted. Most built-in libraries, such as the jQuery Validation plug-in, operate this way. Rather than check each field for mandatory or correct values as your users tab through, you only apply the validation rules when the form is submitted. This way people who want to fill out the form in a different order may do so without getting hit with irritating validation messages as they tab through. This approach is a friendlier technique for those people using a keyboard, rather than a mouse, to fill in the form. Or you can use a mix of both: field-level validation for correct data type and format, form-level validation for required values.

Attempting to submit a form with inaccurate form field entries

Figure 14-2. Attempting to submit a form with inaccurate form field entries

Using JavaScript to highlight a form field with incorrect and missing data is only one part of the form submission process. You’ll also have to account for JavaScript being turned off, which means you have to provide the same level of feedback when processing the form information on the server, and providing the result on a separate page.

It’s also important to mark if a form field is required ahead of time. Use an asterisk in the form field label, with a note that all form fields with an asterisk are required. Use the aria-required attribute to ensure this information is communicated to those using assistive devices.

See Also

See Recipe 14.1 for more information about displaying and hiding page sections, such as messages, and Recipe 14.2 for information about displaying error messages and other alerts.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required