Let’s learn about how to use JavaScript to validate your forms.

In a previous lecture, you’ve learned how to use HTML to restrict the values your users can submit in your form. But sometimes that’s not enough. If you want to get more complex, such as displaying your own error messages to the user, you will need to use JavaScript.

Certain HTML elements, such as the textarea and input elements, expose a Constraint Validation API. This API allows you to assert that the user’s provided value for that element passes any HTML-level validation you have written, such as minimum length or pattern matching.

But how can you actually use it? Let’s say you wanted employees at a company to send feedback messages through a form like this:

<form>
  <label>Enter your email: </label>
  <input required type="email" />
 
  <label>Enter your feedback: </label>
  <textarea required placeholder="Your feedback here..."></textarea>
 
  <button type="submit">Submit Feedback</button>
</form>

We are using the email input which comes with built in validation to check for basic validation like if the input includes the at (@) sign.

But what if the user provides an email address like example@email.com? This would pass the basic validation, but we want to be more specific about accepting emails from those with a company email address.

This is where we can use the pattern attribute to specify that the email address must end in a company email address. Here is what the updated example will look like:

<form>
  <label>Enter your email: </label>
  <input required placeholder="username@sampleCompany.com" type="email" pattern=".+@sampleCompany\.com" />
 
  <label>Enter your feedback: </label>
  <textarea required placeholder="Your feedback here..."></textarea>
 
  <button type="submit">Submit Feedback</button>
</form>

Now, if you try to submit the feedback, you will see a message saying “Please match the requested format.”

Even though the input does have placeholder text showing them the desired format, it would be better to also include a customized error message using JavaScript.

Let’s first take a look at the checkValidity() method:

const input = document.querySelector("input");
 
input.addEventListener("input", (e) => {
  console.log(e.target.checkValidity())
})

In the above example, we’ve queried our input from the DOM, and added an input event listener.

We know that e.target refers to the element that triggered the event. In this case, our input. But what is the checkValidity() method?

This is part of the Constraint Validation API. The checkValidity() method returns true if the element matches all HTML validation (based on its attributes), and false if it fails.

When we try with an invalid input, we see false gets logged in the console. Now that we know the input is invalid, let’s report the invalidity:

const input = document.querySelector("input");
 
input.addEventListener("input", (e) => {
  if (!e.target.checkValidity()) {
    e.target.reportValidity();
  }
})

And as a result, you will see the browser’s error message “Please match the requested format.”

It reports the invalid state immediately, instead of waiting for us to submit the form. But it’s still using the default message. This is because the reportValidity method only tells the browser that the input is invalid. The browser still chooses how to display why it’s invalid. That’s where the setCustomValidity method comes in.

const input = document.querySelector("input");
 
input.addEventListener("input", (e) => {
  if (!e.target.checkValidity()) {
    e.target.setCustomValidity(
      "You must use a company email address that ends in @sampleCompany.com"
    );
  }
});

This method accepts a custom error message, which is displayed to the user. As a result, you will see the custom error message You must use a company email address that ends in @sampleCompany.com.

If you are interested in exploring more about the different types of validity states and why a particular validation has failed, you can log out the validity property like this:

const input = document.querySelector("input");
 
input.addEventListener("input", (e) => {
  console.log(e.target.validity);
})

The validity property is an instance of the ValidityState object. Here is an example of what the object might look like in the browser:

ValidityState {
  badInput: false,
  customError: false,
  patternMismatch: true,
  rangeOverflow: false,
  rangeUnderflow: false,
  stepMismatch: false,
  tooLong: false,
  tooShort: false,
  typeMismatch: true,
  valueMissing: false,
  valid: true
}

There are several helpful properties which all hold the value of a boolean of true or false.

Some of these helpful properties that you can explore more on your own would be the valueMissing property which is true when a required input field is left empty. Or the patternMismatch which is true if the value doesn’t match the specified regular expression pattern.

After this lecture video, I encourage you to play around with the examples shown in this video and explore more about the different validity properties.