Topic 08 / 15

Events — Listeners, Forms & Delegation

~10 min read  //  JavaScript Series  //  Coding India

Listening for Events

const btn = document.querySelector("#save");

btn.addEventListener("click", () => {
  console.log("saved!");
});

Common events: click, input (every keystroke), change (after editing finishes), submit, keydown, mouseover, scroll, DOMContentLoaded. Never use inline onclick="" attributes — keep behaviour in JS files.

The Event Object

Your handler receives an object describing what happened:

input.addEventListener("input", (e) => {
  console.log(e.target.value);     // e.target = the element that fired
});

document.addEventListener("keydown", (e) => {
  if (e.key === "Escape") closeModal();
  if (e.ctrlKey && e.key === "s") {
    e.preventDefault();            // stop the browser's save dialog
    save();
  }
});

Forms — the preventDefault Pattern

Browsers reload the page on form submit. Intercept it:

const form = document.querySelector("#signup");

form.addEventListener("submit", (e) => {
  e.preventDefault();                       // stop the reload

  const data = new FormData(form);
  const email = data.get("email");

  if (!email.includes("@")) {
    showError("Enter a valid email");
    return;
  }
  submitToServer({ email });
});

Listen on the form’s submit, not the button’s click — submit also fires on Enter.

Bubbling — Events Travel Up

A click on a button inside a card inside the body fires on all three, innermost first. That’s bubbling, and it enables the most useful event pattern of all:

Event Delegation

Instead of attaching 100 listeners to 100 list items, attach one to their parent and check what was clicked:

const list = document.querySelector("#todo-list");

list.addEventListener("click", (e) => {
  const deleteBtn = e.target.closest(".delete");
  if (deleteBtn) {
    deleteBtn.closest("li").remove();
  }
});

Delegation works for elements added later too — dynamic lists just work. This is the pattern frameworks use internally.

Removing Listeners & Options

function onScroll() { ... }
window.addEventListener("scroll", onScroll);
window.removeEventListener("scroll", onScroll);   // must be the SAME function

btn.addEventListener("click", once, { once: true });   // auto-removes after one run