โ† All JavaScript lessons

JavaScript / Chapter 04

DOM, Events & Forms

Connect JavaScript to documents, select and update elements, respond to events, validate forms, and build accessible interactive interfaces.

Chapter roadmap

Connect JavaScript to documents, select and update elements, respond to events, validate forms, and build accessible interactive interfaces. Work through the concepts in order, type every example yourself, and keep a short debugging log that records predictions, errors, fixes, and what each fix taught you.

Learning objectives

  • Select and create DOM nodes
  • Handle events
  • Validate and submit forms
  • Maintain accessible interface state

04.1

Selecting and changing elements

The DOM represents a document as nodes. querySelector returns the first matching element and querySelectorAll returns a static collection. Prefer textContent for plain text, classList for styling state, and createElement for new structure instead of building untrusted HTML strings.

Before running the example, trace each expression and write down the expected state or result. Then run it, compare the actual result, and change one input or rule to confirm that you understand which part controls the behavior.

Example
const heading = document.querySelector("h1");
heading.textContent = "Room310 Study";
heading.classList.add("ready");

const note = document.createElement("p");
note.textContent = "Lesson loaded.";
document.querySelector("main").append(note);
Result
The heading and document update without replacing the page.
Check your understanding

Explain the example in plain language, identify one boundary or failure case, and revise it so the output changes in a predictable way.

04.2

Events and delegation

addEventListener connects an event to a handler. The event object describes the target, keyboard input, pointer position, or form action. Event delegation attaches one handler to a stable ancestor and uses closest to respond to matching descendants.

Before running the example, trace each expression and write down the expected state or result. Then run it, compare the actual result, and change one input or rule to confirm that you understand which part controls the behavior.

Example
document.querySelector(".task-list").addEventListener("click", event => {
  const button = event.target.closest("button[data-remove]");
  if (!button) return;
  button.closest("li").remove();
});
Result
Clicking any remove button deletes its list item, including items added later.
Check your understanding

Explain the example in plain language, identify one boundary or failure case, and revise it so the output changes in a predictable way.

04.3

Forms and validation

A submit handler should prevent the default navigation when JavaScript manages the form. FormData reads named fields. Validate required formats and cross-field rules, show messages near the affected control, and keep server-side validation for any real application.

Before running the example, trace each expression and write down the expected state or result. Then run it, compare the actual result, and change one input or rule to confirm that you understand which part controls the behavior.

Example
form.addEventListener("submit", event => {
  event.preventDefault();
  const data = new FormData(form);
  const title = String(data.get("title") ?? "").trim();
  if (!title) {
    showError("title", "Enter a title.");
    return;
  }
  addTask(title);
  form.reset();
});
Result
Blank titles show an error; valid titles are added and the form resets.
Check your understanding

Explain the example in plain language, identify one boundary or failure case, and revise it so the output changes in a predictable way.

04.4

Rendering state accessibly

Interactive interfaces should derive visible output from a clear state object or array. Buttons need accessible names, focus should move intentionally after major changes, and status updates can use an aria-live region. Keyboard and pointer users should receive equivalent behavior.

Before running the example, trace each expression and write down the expected state or result. Then run it, compare the actual result, and change one input or rule to confirm that you understand which part controls the behavior.

Example
const state = { tasks: [] };
function render() {
  list.replaceChildren(...state.tasks.map(task => {
    const item = document.createElement("li");
    item.textContent = task.title;
    return item;
  }));
  status.textContent = `${state.tasks.length} tasks`;
}
Result
The list and live status always reflect the current state.
Check your understanding

Explain the example in plain language, identify one boundary or failure case, and revise it so the output changes in a predictable way.

Chapter assignments

Complete these in order. Later assignments assume that earlier skills are working. Do not only test the sample values; design tests that challenge boundaries, missing values, incorrect types, empty collections, and other likely failures.

  1. A4.1

    Create controls that change page theme, font size, and spacing while keeping button states accessible.

    Submit readable source code, a brief design note, and evidence from at least three tests including one boundary or invalid case.

  2. A4.2

    Build an interactive list with event delegation for complete, edit, and remove actions.

    Submit readable source code, a brief design note, and evidence from at least three tests including one boundary or invalid case.

  3. A4.3

    Create a registration form with inline validation, summary errors, and keyboard-friendly focus behavior.

    Submit readable source code, a brief design note, and evidence from at least three tests including one boundary or invalid case.

  4. A4.4

    Render a searchable, sortable table from an array of objects without using innerHTML.

    Submit readable source code, a brief design note, and evidence from at least three tests including one boundary or invalid case.

Chapter project

Accessible Task Board

Accessible Task Board โ€” Build add, edit, complete, filter, and delete behavior from a central state array. Use semantic HTML, delegated events, form validation, keyboard-accessible controls, and an aria-live status summary.

Required process

  1. Write a short specification listing inputs, outputs, rules, and failure cases.
  2. Break the work into small functions, queries, modules, or classes appropriate to the language.
  3. Build the smallest working version before adding optional features.
  4. Test normal, boundary, empty, and invalid cases and record the results.
  5. Refactor names and duplication, then write a concise user guide.

Key terms

  • DOM
  • node
  • selector
  • event
  • handler
  • delegation
  • FormData
  • validation
  • focus
  • aria-live