Reading What People Type

Read what a visitor typed, ticked and chose in a form with value and checked, turn text into numbers, and collect a whole form at once with form.elements or FormData.

Apprentice · JavaScript · HTML · Updated

After this lesson you can

  • Read what a visitor typed or chose with value and checked, and turn a number box's value into a number
  • Collect a form's fields by name with form.elements or FormData

Key takeaways

  • An input's value is what's in its box, and it's always a string, even in a number box. Convert it with Number() before you do math with it.
  • A checkbox's checked is true or false. Its value is "on" whether it's ticked or not, so read checked.
  • A select's value is the value of the chosen option, such as "reading", not the words the visitor sees.
  • form.elements finds every field of a form by its name, such as form.elements.title.
  • new FormData(form) collects every named field at once. Its get() gives a string, or null for a checkbox that isn't ticked.

Sign-up pages, search boxes, checkout pages, comment boxes, a "how many tickets?" picker: nearly every website asks people to type something. Whatever they type, your JavaScript's first job is the same: read it. This lesson shows how, using a page you'll keep through this chapter, My Reading List, where a reader adds the books they want to read, are reading, and have finished.

A form on a page

Think of a paper form at the library: a box for the title, a box for the author, a few choices to circle, a box to tick. A web form is the same idea. The HTML You Need for JavaScript met the form, its labels and its boxes. Here they are again, with two new ones, the tick box and the list to choose from:

  • <form> wraps the whole form, like the sheet of paper.
  • <input> is one box to fill in. Its type says what kind: text for words, number for a number, checkbox for a tick box.
  • <select> is a list to choose from, with one <option> per choice.
  • <label> is the printed words beside a box. Its for matches the box's id, so clicking the words puts the cursor in the box, and a screen reader reads them aloud.
  • name is the name a field goes by when the form is collected, like the field names a library clerk types into the computer.

Here's the Reading List's form. It's part of the page, not a whole file:

<form id="add-book">
  <label for="title">Title</label>
  <input id="title" name="title" type="text">

  <label for="pages">Pages</label>
  <input id="pages" name="pages" type="number">

  <label for="status">Status</label>
  <select id="status" name="status">
    <option value="want-to-read">Want to read</option>
    <option value="reading">Reading</option>
    <option value="finished">Finished</option>
  </select>

  <label><input id="favorite" name="favorite" type="checkbox"> One of my favorites</label>
  <button type="submit">Add book</button>
</form>

value: what's in the box, always as text

Every box has a value property: whatever is in it right now. Find the box, as you did in Locating DOM elements, and read it:

const titleInput = document.getElementById("title");
const pagesInput = document.getElementById("pages");

console.log(titleInput.value);
console.log(pagesInput.value);

titleInput.value = "";

With The Hobbit and 310 typed in, the Console shows The Hobbit and 310. Setting value changes the box too: the last line empties it, which you'll do after a book is added.

Here's the catch. A box's value is always a string, even in a number box: what arrives is the text "310", not the number 310. Do math with it as it is and you get a surprise. You can see it in Node, with the text a number box would give you:

const pagesFromForm = "310";

console.log(pagesFromForm + 10);
console.log(Number(pagesFromForm) + 10);
console.log(typeof pagesFromForm);
console.log(Number(""));
31010
320
string
0

With text on one side, + joins instead of adding. Number(), from Types and Converting Between Them, turns the text into a number first. Watch the last line too: an empty box gives "", and Number("") is 0. So a reader who leaves Pages empty sends you 0 pages, which the lesson Checking a Form with JavaScript teaches you to catch.

checked: a yes-or-no box, and a list's choice

A tick box is a yes-or-no question, so the property to read is checked: true when it's ticked, false when it isn't. A <select> has a value like a text box, and it's the value of the chosen <option>:

const favoriteBox = document.getElementById("favorite");
const statusList = document.getElementById("status");

console.log(favoriteBox.checked);
console.log(favoriteBox.value);
console.log(statusList.value);

With nothing ticked and Want to read chosen, the Console shows false, on and want-to-read. Two traps live here:

  • A checkbox's value is "on" whether it's ticked or not. It never tells you the answer; checked does.
  • A list's value is the option's value attribute, "want-to-read", not the words the reader sees, Want to read. That's handy: your code works with short, steady names, and the words on the page can change without breaking it.

form.elements: every field by its name

Finding five boxes one at a time gets long. A form keeps a list of its own fields, form.elements, and you can ask it for any field by its name, with a dot or with square brackets:

const form = document.getElementById("add-book");
const fields = form.elements;

const book = {
  title: fields.title.value.trim(),
  pages: Number(fields["pages"].value),
  status: fields.status.value,
  favorite: fields.favorite.checked,
};

console.log(book);

That builds one book object, the kind you worked with in Arrays of Objects, straight from the form: the title with its spaces trimmed off (trim(), from String Methods), the pages as a real number, the status, and true or false for a favorite. Building one object from a form like this is what most form code does.

FormData: the whole form in one go

Sometimes you want everything at once, for example to save it or send it to a server. new FormData(form) reads every field that has a name, the way the browser does when it sends a form. You ask it for a field with get:

const form = document.getElementById("add-book");
const data = new FormData(form);

console.log(data.get("title"));
console.log(data.get("favorite"));
console.log(Object.fromEntries(data));

get always gives a string, the same as value. A checkbox that isn't ticked isn't in the form data at all, so get("favorite") gives null; ticked, it gives "on". Object.fromEntries(data) turns the whole thing into one plain object, every value a string.

FormData exists in Node too, without a form, so you can try what it gives back. Here it's filled by hand with append, the way the browser fills it from a form:

const data = new FormData();
data.append("title", "The Hobbit");
data.append("pages", "310");

console.log(data.get("title"));
console.log(data.get("pages") + 1);
console.log(data.get("favorite"));
console.log(data.has("favorite"));
The Hobbit
3101
null
false

The pages are still text, so + 1 joins. And there's no "favorite" at all: has answers false, and get gives null, which is how an unticked box looks.

Which one when? Read value or checked when you need one or two fields. Use form.elements when you're building an object field by field and converting as you go. Use FormData when you want every field at once, as strings.

Try it. Make a folder named reading-list with an empty app.js and an index.html that holds the whole page below. Open it with Live Preview, as in JavaScript on a Web Page, type a book into the form, and in the Console type document.getElementById("pages").value. The answer is in quotes: the Console's way of showing a string. Then try document.getElementById("favorite").checked, before and after ticking the box. (Pressing Add book reloads the page and empties the form for now. Canceling Events shows how to stop that.)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>My Reading List</title>
</head>
<body>
  <h1>My Reading List</h1>
  <form id="add-book">
    <label for="title">Title</label>
    <input id="title" name="title" type="text">
    <label for="author">Author</label>
    <input id="author" name="author" type="text">
    <label for="pages">Pages</label>
    <input id="pages" name="pages" type="number">
    <label for="status">Status</label>
    <select id="status" name="status">
      <option value="want-to-read">Want to read</option>
      <option value="reading">Reading</option>
      <option value="finished">Finished</option>
    </select>
    <label><input id="favorite" name="favorite" type="checkbox"> One of my favorites</label>
    <button type="submit">Add book</button>
  </form>
  <ul id="books"></ul>
  <script type="module" src="app.js"></script>
</body>
</html>

Check yourself

2 questions to try on the lesson page.

So what

Every form your code ever handles, from a pizza order to a job application, starts the same way: read value and checked, turn the text into the types you need, and build one object from it. The rest of this chapter checks that object, and then remembers it.

Key terms

Cheat sheets

Related