---
id: 6733aae9d25004f60d1e86f2
title: What Are Some Ways to Validate Forms Using JavaScript?
challengeType: 19
dashedName: what-are-some-ways-to-validate-forms-using-javascript
---

# --interactive--

In a previous lesson, 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:

:::interactive_editor

```html
<link rel="stylesheet" href="styles.css" />
<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>
```

```css
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}

```

:::

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:

:::interactive_editor

```html
<link rel="stylesheet" href="styles.css" />
<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>
```

```css
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}

```

:::

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:

:::interactive_editor

```html
<link rel="stylesheet" href="styles.css" />
<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>
<script src="index.js"></script>
```

```css
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}

```

```js
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:

:::interactive_editor

```html
<link rel="stylesheet" href="styles.css" />
<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>
<script src="index.js"></script>
```

```css
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}

```

```js
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.

:::interactive_editor

```html
<link rel="stylesheet" href="styles.css" />
<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>
<script src="index.js"></script>
```

```css
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}

```

```js
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:

:::interactive_editor

```html
<link rel="stylesheet" href="styles.css" />
<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>
<script src="index.js"></script>
```

```css
form {
  max-width: 400px;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}

label {
  font-weight: 600;
  margin-bottom: 4px;
  color: #333;
}

input,
textarea {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.2s, box-shadow 0.2s;
}

input:focus,
textarea:focus {
  border-color: #0078d4;
  box-shadow: 0 0 3px rgba(0, 120, 212, 0.5);
  outline: none;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

button[type="submit"] {
  background-color: #0078d4;
  color: #fff;
  border: none;
  padding: 10px 16px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button[type="submit"]:hover {
  background-color: #005ea2;
}

```

```js
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:

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

There are several helpful properties which all hold a boolean value 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` property, which is `true` if the value doesn't match the specified regular expression pattern.

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

# --questions--

## --text--

Which method of the Constraint Validation API is used to check if an input element meets all its validation constraints?

## --answers--

`validateInput()`

### --feedback--

The lesson demonstrates this method when adding an event listener to the input element.

---

`checkValidity()`

---

`isValid()`

### --feedback--

The lesson demonstrates this method when adding an event listener to the input element.

---

`testConstraints()`

### --feedback--

The lesson demonstrates this method when adding an event listener to the input element.

## --video-solution--

2

## --text--

What is the purpose of the `setCustomValidity()` method in form validation?

## --answers--

To set custom CSS styles for invalid inputs.

### --feedback--

The lesson explains how this method is used to provide more informative feedback to users.

---

To create custom validation rules.

### --feedback--

The lesson explains how this method is used to provide more informative feedback to users.

---

To display a custom error message for invalid inputs.

---

To override the default HTML validation.

### --feedback--

The lesson explains how this method is used to provide more informative feedback to users.

## --video-solution--

3

## --text--

Which property of the `validity` object becomes true when a required input field is left empty?

## --answers--

`isEmpty`

### --feedback--

The lesson shows this property when logging the `validity` object for an empty required field.

---

`required`

### --feedback--

The lesson shows this property when logging the `validity` object for an empty required field.

---

`valueMissing`

---

`invalidValue`

### --feedback--

The lesson shows this property when logging the `validity` object for an empty required field.

## --video-solution--

3
