To-do App That Remembers
1.5 hBeginnerJavaScriptDOMEventsArrayslocalStorage
Outcome
A to-do list where you can add tasks, tick them off, delete them, filter All / Active / Completed, see how many are left — and find everything still there after reloading the page.
Learning objectives
- ▸Keep app state in one array and redraw the DOM from it with a
render()function - ▸Create elements with
document.createElementand attach event listeners to them - ▸Use
filter,findandpushto update and query an array of objects - ▸Persist data with
localStorage,JSON.stringifyandJSON.parse
Prerequisites
- •JavaScript basics: variables, functions, arrays, objects and
addEventListener— see the JavaScript track - •Comfortable reading simple HTML forms (the Tip & Bill Splitter project is good practice)
Expected behaviour
- ✓Typing a task and pressing Enter (or Add) adds it to the list and clears the input. Blank tasks are ignored.
- ✓Ticking a task's checkbox crosses it out; unticking restores it. The Delete button removes it.
- ✓All / Active / Completed show the matching tasks, and “N items left” is always correct.
- ✓After a refresh, every task (and whether it's done) is still there.
Almost every app you'll ever build follows the same loop: something happens → update the state → redraw the screen. A to-do list is the smallest app that shows this loop clearly, which is why every developer builds one.
let todos = [
{ id: "a1", text: "Beli susu", done: false },
{ id: "b2", text: "Siapkan assignment", done: true },
];
// event → change the array → render() redraws everything from itThe array is the truth. The list on screen is just a picture of it.
filter (delete, filter views) and find (toggle) a lot in this project.The preview emulates localStorage per project, and it's kept between check runs — so items you add while testing may still be there next time. That's the feature working!
Milestones
Make the form work:
1. Listen for the form's submit event and call event.preventDefault().
2. Read input.value.trim(). If it's empty, stop.
3. Push an object like { id, text, done: false } into todos.
4. Clear the input and call render().
Then write render(): empty the list (list.innerHTML = "") and create one <li> per to-do with the text inside a <span>. Use textContent for the text — never innerHTML for user input.
Checks
- Submitting adds an
<li>with the text - The to-do is stored in the
todosarray - The input is cleared after adding
- Blank input is ignored
Console output from your code appears here.