30 Days Of JavaScript

Day 18: Forms

Lesson 2: Form Validation

Click the Add button with the form empty. See how we add an entry to our list that looks like this : $ x? That's dumb right?

Well let's use some HTML to make our values required.

Change your form to look like this.

1<form id="stock-form">
2  <label for="name">Broom Name</label>
3  <input type="text" name="name" required />
4  <label for="price">Price</label>
5  <input type="number" name="price" required />
6  <label for="quantity">Quantity</label>
7  <input type="number" name="quantity" required />
8  <button type="submit">Add</button>
9</form>

Now click Add and you'll see we get a note to tell us that the fields are required. And we didn't need to write any JavaScript at all!

What if we want a more complicated validation? Let's say we know that our shop only stocks a certain range of brooms, let's say the Comet and the Nimbus ranges and we don't want to accept any other types.

Firstly change your Add button to this.

1<button type="submit" id="form-submit" disabled>Add</button>

And then add this to the end of your JavaScript section.

1const handleOnInput = (e) => {
2  const formData = new FormData(e.currentTarget);
3  const formProps = Object.fromEntries(formData);
4
5  let nameValid = false;
6
7  if (
8    formProps.name.toLowerCase().includes("nimbus") ||
9    formProps.name.toLowerCase().includes("comet")
10  ) {
11    nameValid = true;
12  }
13
14  const priceValid = !isNaN(parseInt(formProps.price));
15  const quantityValid = !isNaN(parseInt(formProps.quantity));
16
17  if (nameValid && priceValid && quantityValid) {
18    document.getElementById("form-submit").disabled = false;
19  } else {
20    document.getElementById("form-submit").disabled = true;
21  }
22};
23
24form.oninput = handleOnInput;

There's lot going on here so let's break it down.

We create an function called handleOnInput that we attach to the form's oninput event handler. The oninput event fires every time there is input into the form, so every key press on the form will fire this event handler.

In handleOnInput we get the form fields as a nice object. We have to change the target as while the event handler is on the form, the element actually first firing the event is the input field that changed. So, where as with onsubmit we could just use e.target to get the reference to the <form> we now need to use e.currentTarget to get it instead.

1const formData = new FormData(e.currentTarget);
2const formProps = Object.fromEntries(formData);

We then create a variable to determine if the name is valid, we start with it being false.

We then check to see if name includes the substring nimbus or comet. We make the string from the user lowercase first so it's easier to compare. If comet or nimbus appear in the name string then we assume it's valid and set nameValid = true.

1if (
2  formProps.name.toLowerCase().includes("nimbus") ||
3  formProps.name.toLowerCase().includes("comet")
4) {
5  nameValid = true;
6}

Next up we need to check if the number fields have valid numbers. This is trickier that you would expect as we will have been given them as strings and not numbers. So we need to use the function parseInt() to see if there is a valid number in the string. If there isn't then we will get sent back NaN, which literally stands for Not a Number.

Which sounds handy but it's not because NaN's origins are routed in complicated floating point math and so the best thing to do is use the function isNaN to determine if we have a valid number or NaN.

We land up with.

1const priceValid = !isNaN(parseInt(formProps.price));
2const quantityValid = !isNaN(parseInt(formProps.quantity));

To check if price and quantity are numbers.

How is NaN weird you might ask? Well I won't go into great detail but I will leave you with the note that NaN isn't equal to itself.

That's right, where 1 == 1 and 'a' === 'a' will be be true, NaN === NaN will be false.

Then finally we check if all fields are valid, if they are we set the button's disabled to false and if they aren't then we set it to true.

The reason we actually include the else side of this is that if we didn't, someone could make valid entries and then go back, edit a field and the button would still be enabled.

Outline

Go Pro?

Upgrade to Pro for quizzes, tracked progress and a completion certificate for just $25 🚀

Want more developer tips, tricks and tools?
Then follow me:
FREE Coding Career Quick Start Guide 🚀
Discover the best way to learn to code, how to land a job and valuable resources to help your journey in this free 15 page value packed guide.
Looking to email me? You can get me on my first name at allthecode.co