I built a simple Todo List App using JavaScript — something that keeps track of tasks quietly in the background, ready whenever I need it.
👉 You can try it here:
This blog isn’t just about what I built — it’s about how it works, especially the JavaScript behind it. I’ll walk you through it in a way that actually makes sense, even if you’re just getting started.
What This Todo App Can Do
Here’s what the app handles:
- Add new tasks
- Edit existing tasks
- Delete tasks
- Mark tasks as completed
- Save everything using localStorage (even after refresh)
It’s simple, but it covers the core ideas every beginner needs to understand.
Where Everything Lives and Stays
let todos = JSON.parse(localStorage.getItem("vals")) || [];
What’s happening here?
- The app checks if there are already saved tasks in localStorage
- If yes, it converts them back into a usable array
- If not, it starts fresh with an empty list
Think of localStorage as a small shelf where your tasks stay even when you leave and come back.
Locking Things in Place
function savedata() {
localStorage.setItem("vals", JSON.stringify(todos));
}
This function makes sure your tasks don’t disappear.
- It converts the array into a string
- Then stores it in the browser
Since localStorage only understands text, we use JSON.stringify() to make it readable.
Rebuilding the Screen Every Time
function renderTodos() {
logg.innerHTML = "";
Before showing anything, the app clears what’s already on the screen.
Why?
Because instead of updating one item at a time, it rebuilds the entire list cleanly every time something changes.
Going Through Each Task
todos.forEach((todo, index) => {
This loop goes through every task and creates its visual representation.
Showing the Task
const span = document.createElement("span");
span.innerText = todo.text;
Each task is placed inside a span element.
Marking It Done
if (todo.done) span.classList.add("done");
If a task is completed, it gets a line-through style.
Toggling Completion
span.addEventListener("click", () => {
todo.done = !todo.done;
savedata();
renderTodos();
});
Clicking on a task flips its state:
- If it was incomplete, it becomes complete
- If it was complete, it goes back
Then the app saves and refreshes everything.
Editing a Task
edit.addEventListener("click", () => {
userinput.value = todo.text;
editIndex = index;
btn.innerText = "Update";
});
When you click edit:
- The task text is placed back into the input field
- The app remembers which task you’re editing
- The button changes from "Add" to "Update"
Removing a Task
del.addEventListener("click", () => {
todos.splice(index, 1);
savedata();
renderTodos();
});
This removes the selected task from the list, updates storage, and refreshes the display.
One Function Handling Two Jobs
function handleTask() {
This function decides whether to add a new task or update an existing one.
Avoiding Empty Entries
if (val === "") return;
No empty tasks are allowed.
Adding a New Task
todos.push({ text: val, done: false });
A new task is added as an object with two properties:
- text
- done
Updating an Existing Task
todos[editIndex].text = val;
editIndex = -1;
btn.innerText = "Add";
The selected task is updated, and the app exits edit mode.
Final Steps
userinput.value = "";
savedata();
renderTodos();
After any change:
- The input is cleared
- Data is saved
- The UI is refreshed
A Small but Important Interaction
userinput.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
handleTask();
}
});
Pressing Enter triggers the same action as clicking the button.
This small addition makes the app feel much smoother to use.
What This Project Really Teaches
Even though the app looks simple, it introduces key concepts:
- How to work with the DOM
- How to handle user events
- How to manage data using arrays and objects
- How to store data in the browser
- How to keep UI and data in sync
These are the exact building blocks used in larger applications.
Why Building Something Like This Matters
Watching tutorials can only take you so far.
When you build something yourself:
- You start understanding why things work
- You make mistakes and learn from them
- You begin thinking like a developer
This is where real progress happens.
What Would You Add Next?
If you want to take this further, you could try:
- Adding due dates
- Setting priorities
- Creating a dark mode
- Improving animations
Each improvement adds another layer of understanding.
Final Thoughts
If you’ve read this far, you’re not just scrolling — you’re trying to understand.
And that matters.
Every line of code in this project represents a step forward. Not just in JavaScript, but in how you approach problems, break them down, and build solutions from scratch.
So here’s something to think about:
What’s the next small idea you’ve been putting off building?
Start it. Keep it simple. Let it grow.
And when you do, you’ll realize this wasn’t just about a todo app — it was about learning how to turn ideas into something real.
Top comments (0)