Building a To-Do List with Vanilla JavaScript is a practical way to improve your frontend skills. This project runs in any web browser and uses no external libraries. It helps you learn DOM manipulation, event handling, and dynamic UI updates.
What Is a To-Do List App?
A To-Do List app lets users manage daily tasks. Creating one from scratch strengthens your understanding of how web pages respond to user actions. Key features include:
- Adding Tasks: Capture input and add it to a list.
- Rendering Tasks: Display tasks dynamically in the browser.
- Editing Tasks: Update tasks inline.
- Deleting Tasks: Remove tasks from the list.
- Using localStorage: Keep tasks saved after refresh.
This project helps you grasp how the DOM works and lays the foundation for using modern JavaScript frameworks.
How to Build the To-Do App
Start with a simple HTML layout. Then use JavaScript to manage the list: store tasks in an array, render them in the DOM, and respond to user actions. You'll use addEventListener
, createElement
, and other basic DOM methods.
Set Up the HTML
Start with a simple HTML structure.
<!DOCTYPE html>
<html>
<head>
<title>To-Do List</title>
</head>
<body>
<h2>To-Do List</h2>
<input type="text" id="taskInput" placeholder="Write a task..." />
<button id="submit">Submit</button>
<ul id="taskList"></ul>
<script src="todo.js"></script>
</body>
</html>
Add JavaScript Logic
Create a todo.js
file and write the logic.
// Array to store tasks
const todos = [];
// Get DOM elements
const input = document.getElementById('taskInput');
const submit = document.getElementById('submit');
const list = document.getElementById('taskList');
// Load saved tasks from localStorage when page loads
window.addEventListener('DOMContentLoaded', () => {
const saved = JSON.parse(localStorage.getItem('todos')) || [];
todos.push(...saved); // Load existing tasks into the array
renderTodos(); // Display tasks in the UI
});
// Handle submit button click
submit.addEventListener('click', addTodo);
// Add a new task
function addTodo() {
const text = input.value.trim();
if (!text) return alert('Please write something');
// Add task with unique ID
todos.push({ id: Date.now(), text });
input.value = ''; // Clear input field
updateStorage(); // Save to localStorage
renderTodos(); // Update UI
}
// Display all tasks in the list
function renderTodos() {
list.innerHTML = ''; // Clear previous list
todos.forEach(todo => {
const li = document.createElement('li');
li.dataset.id = todo.id;
// Show task text
const span = document.createElement('span');
span.innerText = todo.text;
li.appendChild(span);
// Add Edit button
const editBtn = document.createElement('button');
editBtn.innerText = 'Edit';
editBtn.onclick = () => enterEditMode(li, todo);
li.appendChild(editBtn);
// Add Delete button
const deleteBtn = document.createElement('button');
deleteBtn.innerText = 'Delete';
deleteBtn.onclick = () => deleteTodo(todo.id);
li.appendChild(deleteBtn);
list.appendChild(li);
});
}
// Delete a task by ID
function deleteTodo(id) {
const index = todos.findIndex(t => t.id === id);
if (index !== -1) {
todos.splice(index, 1); // Remove from array
updateStorage(); // Update localStorage
renderTodos(); // Refresh UI
}
}
// Switch task to edit mode
function enterEditMode(li, todo) {
li.innerHTML = ''; // Clear existing content
// Create input to edit task text
const inputEdit = document.createElement('input');
inputEdit.value = todo.text;
li.appendChild(inputEdit);
// Save button for updated task
const saveBtn = document.createElement('button');
saveBtn.innerText = 'Save';
saveBtn.onclick = () => {
const newText = inputEdit.value.trim();
if (newText) {
todo.text = newText; // Update task text
updateStorage(); // Save to localStorage
renderTodos(); // Re-render list
}
};
li.appendChild(saveBtn);
}
// Save current tasks to localStorage
function updateStorage() {
localStorage.setItem('todos', JSON.stringify(todos));
}
How It Works
- Load Tasks: On page load, saved tasks are fetched from
localStorage
and displayed. - Add Task: Enter text and click "Submit" to add a new task with a unique ID.
- Render Tasks: The
renderTodos()
function updates the list in the browser. - Edit Task: Clicking "Edit" replaces the task with an input and a "Save" button to update the text.
- Delete Task: Clicking "Delete" removes the task from the array and updates the list.
- Save to localStorage: All changes—add, edit, delete—are stored in
localStorage
to retain tasks after refresh.
This setup keeps your task list functional, dynamic, and persistent in the browser without using a backend.
Conclusion
You've learned how to build a functional To-Do List using only JavaScript. You handled user input, updated the DOM, and managed tasks in an array. You also implemented localStorage
to keep tasks saved even after refreshing the page. These core skills are essential for developing responsive, browser-based applications.