30 Days Of JavaScript

Day 22: Consolidation 5

Lesson 2: Forms

Forms are how we take user input. They have an onsubmit event that we can add a function call to, this allows us to access the form and do what we need to.

They have an action attribute, the url in there is where the form will submit it's data to. If we don't want to submit data to that URL then we need to make sure we call e.preventDefault() in our event handler at some point, where e is the event passed into our even handler.

Accessing form data can be done easily with the FormData class, then we make an object right from that to get a nice JavaScript object of our form.

1const handleSubmit = (e) => {
2  e.preventDefault();
3
4  const formData = new FormData(e.target);
5  const formProps = Object.fromEntries(formData);
6  console.log(formProps);
7};

If you want to clear a form you can do that with e.target.reset(). So long as the target in the event is the form DOM element. If there is a chance that something other than the form triggered the event, then you will need to use currentTarget.

Validation

HTML input attributes like required can handle a good amount of the validation we will need to do. However if you want something more complicated and keep the submit button disabled until the form is valid, then you will need to add an event handler to the forms oninput event.

In that function you can access the form and all the relevant data to enable or disable the submit button like this:

1const handleOnInput = (e) => {
2  const formData = new FormData(e.currentTarget);
3  const formProps = Object.fromEntries(formData);
4
5  // validation checks
6
7  if (formValid) {
8    document.getElementById("form-submit").disabled = false;
9  } else {
10    document.getElementById("form-submit").disabled = true;
11  }
12};
13
14form.oninput = handleOnInput;

If your form has numbers in you will need to parse them from the string that form gives them to you as.

You do that with parseInt() (or parseFloat() for numbers with decimals) function. If no number is found then it will return NaN and then you need to use isNaN to check if you have a valid number or not.

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

Async forms

Most of the time our form data will get submitted to a server or backend of some kind. To do that we need to be aware of good UI and UX practices, such as disabling the form before submitting the data and reenabling it when we get a response from the server.

The common pattern for this is:

1const handleSubmit = (e) => {
2  e.preventDefault();
3
4  const formData = new FormData(e.target);
5  const formProps = Object.fromEntries(formData);
6
7  // set loading / disabled state
8
9  fetch("https://reqres.in/api/brooms", {
10    method: "POST",
11    headers: {
12      "Content-Type": "application/json",
13    },
14    body: JSON.stringify(formProps),
15  })
16    .then((res) => res.json())
17    .then((data) => {
18      // update the UI here if needed
19      e.target.reset();
20    })
21    .catch((err) => {
22      alter("Whoops, something went wrong");
23      console.error(err.message);
24    })
25    .finally(() => {
26      // clear any loading / disabled state you might have set
27    });
28};

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