Forms

Course 1 · Ch 9
Forms and User Input
Reading what a visitor typed, checking it's valid, and reacting when they submit

Chapter 8 covered reaching into the page and reacting to clicks. The most common real-world use of that is forms — text fields, checkboxes, dropdowns — where a page needs to read what the user typed, check it, and respond. This chapter ties together querySelector, addEventListener, and the conditional logic from Chapter 3 into one practical workflow.

Reading an Input's Value

const nameInput = document.querySelector("#nameInput"); console.log(nameInput.value); // whatever the user has currently typed, as a string

Unlike most elements, a form input's current text lives in its value property — not textContent. value is always a string, even for a number input, which matters when doing arithmetic with it.

Listening for Input Changes

nameInput.addEventListener("input", () => { console.log(`Current value: ${nameInput.value}`); });

The "input" event fires every time the field's value changes — every keystroke, paste, or autofill — making it the right choice for live feedback like character counters or instant validation messages, as opposed to "change", which only fires once the field loses focus.

Handling Form Submission

const form = document.querySelector("#signupForm"); form.addEventListener("submit", (event) => { event.preventDefault(); // stops the page from reloading console.log("Form submitted!"); });

A form's default behaviour on submit is to reload the page and send its data to a server — almost never what's wanted when JavaScript is handling things instead. event.preventDefault() stops that default behaviour, while still letting the rest of the handler run normally.

Forgetting preventDefault() looks like the script "did nothing"
Without it, the page reloads the instant submit happens, wiping out the console and any in-memory state before there's time to even notice the handler ran. If a submit handler appears to silently fail, this is the first thing to check.

Validating Input Before Accepting It

form.addEventListener("submit", (event) => { event.preventDefault(); const name = document.querySelector("#nameInput").value.trim(); const errorBox = document.querySelector("#errorBox"); if (name === "") { errorBox.textContent = "Name is required."; return; } errorBox.textContent = ""; console.log(`Welcome, ${name}!`); });

.trim() removes leading/trailing whitespace, so a field containing only spaces is correctly treated as empty. Using return inside the handler stops execution immediately when validation fails, the same early-exit pattern functions have used since Chapter 5 — nothing after it runs until the user fixes the problem and resubmits.

Checkboxes and Select Dropdowns

const subscribe = document.querySelector("#subscribeCheckbox"); console.log(subscribe.checked); // true or false — NOT value const country = document.querySelector("#countrySelect"); console.log(country.value); // the value of the currently selected

Checkboxes use checked (a boolean) rather than value for their state. Dropdowns (<select>) use value, same as text inputs, returning whichever <option>'s value attribute is currently selected.

ElementRead state withUseful event
Text inputinput.value"input" (live) or "change" (on blur)
Checkboxcheckbox.checked"change"
Select dropdownselect.value"change"
Whole form"submit" (always call event.preventDefault())

Coding Challenges

Challenge 1

Assume an input with id ageInput and a p with id ageOutput. Add an "input" event listener to ageInput that updates ageOutput's textContent live to say "You typed: X" every time the value changes.

📄 View solution
Challenge 2

Assume a form with id loginForm containing an input #username and a p#errorBox. On submit, prevent the default reload, trim the username, and if it's empty show "Username is required." in errorBox; otherwise clear errorBox and log a welcome message.

📄 View solution
Challenge 3

Assume a checkbox #agreeCheckbox and a button #submitBtn that starts disabled. Add a "change" listener to the checkbox that enables submitBtn (button.disabled = false) when checked, and disables it again (button.disabled = true) when unchecked.

📄 View solution

Chapter 9 Quick Reference

  • input.value — current text in an input/textarea/select (always a string)
  • checkbox.checked — boolean state of a checkbox, not value
  • "input" — fires on every keystroke; "change" — fires once focus leaves the field
  • form.addEventListener("submit", ...) — always call event.preventDefault() first
  • .trim() — strips whitespace before checking if a value is "empty"
  • return inside a handler — early-exit pattern for stopping on invalid input
  • element.disabled = true/false — enable/disable form controls dynamically
  • Next chapter: asynchronous JavaScript — fetch, promises, and async/await