Skip to main content
JavaScript & the browser·Module C2 · Lesson 10
TaskBuild the todo list described above. The form adds a typed value as a new <li>. Each <li> has a child <span> with the text + a <button class='remove'>×</button>. Delegation on #list: clicking .remove deletes the li; clicking the span toggles 'done' on the li.

Build a Todo List in Vanilla JavaScript with Event Delegation

250 XP14 min
Theory

Putting C2 together

You'll combine every C2 idea into a working todo list:

  1. Form submit to add an item → C2-06 (preventDefault + FormData)
  2. createElement + textContent to render each item safely → C2-07
  3. Event delegation for the "remove" button on each item → C2-08
  4. classList for the "completed" line-through state → C2-04
  5. querySelector for everything else → C2-02

No framework. ~30 lines of JavaScript. Same skills run any non-trivial framework you'll meet later.

The shape

<form id="f">
  <input id="text" required />
  <button>Add</button>
</form>
<ul id="list"></ul>
const form  = document.getElementById("f");
const input = document.getElementById("text");
const list  = document.getElementById("list");

form.addEventListener("submit", (e) => {
  e.preventDefault();
  const value = input.value.trim();
  if (!value) return;
  const li  = document.createElement("li");
  const txt = document.createElement("span");
  const btn = document.createElement("button");
  txt.textContent = value;
  btn.textContent = "×";
  btn.className   = "remove";
  li.append(txt, btn);
  list.appendChild(li);
  input.value = "";
});

list.addEventListener("click", (e) => {
  if (e.target.closest(".remove")) e.target.closest("li").remove();
  else if (e.target.tagName === "SPAN") e.target.classList.toggle("done");
});

Form adds → delegation handles remove + toggle. Two listeners total, regardless of list length.

🔒

Sign up to start coding

Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial — card required, cancel anytime.

Sign up — free trial →

First 10 lessons in each track are free. No card needed for those.

PreviousNext lesson →

Get one Python or web tip a day — by email

Short, hand-written, no spam. Unsubscribe in one click.