Read Values, Handle Submits, Send `FormData`
JavaScript DOM Forms
Forms are how users send data into your app. Learn to read values, intercept submits, and use the `FormData` API.
What you'll learn
- Read input values and handle changes
- Intercept `submit` and validate inline
- Use `FormData` to grab everything at once
A form is just an HTML element wrapping inputs. JavaScript reads
values via the inputs’ .value, listens for submit on the form,
and (most of the time) prevents the default navigation so you can
send the data with fetch.
Reading One Input
const name = document.querySelector("input[name='name']");
console.log(name.value); // current value
name.addEventListener("input", e => {
console.log("typing:", e.target.value);
}); The input event fires on every keystroke; change fires once when
focus leaves.
Submit Once, Grab Everything
The clean pattern is one submit listener that reads all fields.
const form = document.querySelector("form");
form.addEventListener("submit", e => {
e.preventDefault();
const data = new FormData(form);
for (const [key, value] of data) {
console.log(key, "=", value);
}
}); FormData reads every [name]’d input in the form. It iterates as
[name, value] pairs.
To a Plain Object
const form = document.querySelector("form");
form.addEventListener("submit", e => {
e.preventDefault();
const obj = Object.fromEntries(new FormData(form));
console.log(obj); // { name: "Ada", email: "ada@…" }
}); Send It With fetch
You can pass a FormData straight to fetch’s body. The browser
sets the right Content-Type for you.
form.addEventListener("submit", async e => {
e.preventDefault();
const res = await fetch("/api/signup", {
method: "POST",
body: new FormData(form),
});
if (!res.ok) console.log("failed");
}); For a JSON API, build the object yourself and stringify:
const body = JSON.stringify(Object.fromEntries(new FormData(form)));
fetch("/api/signup", {
method: "POST",
headers: { "content-type": "application/json" },
body,
}); Inline Validation
Inputs have a validity object the browser fills in based on
type, required, pattern, min, max, etc. You can show a
custom message:
const email = document.querySelector("input[type='email']");
email.addEventListener("input", () => {
if (!email.validity.valid) {
email.setCustomValidity("Hmm, that doesn't look like an email.");
} else {
email.setCustomValidity(""); // clear it
}
}); Checkboxes, Radios, Selects
| Control | Read with… |
|---|---|
<input> text/number/email | el.value (always a string) |
<input type="checkbox"> | el.checked (boolean) |
<input type="radio"> | The checked one’s .value (or formData.get(name)) |
<select> | el.value (the selected option’s value) |
<select multiple> | [...el.selectedOptions].map(o => o.value) |
<textarea> | el.value |
Up Next
Most APIs trade JSON. Time to learn how to parse and serialize it.
JavaScript JSON →