Create a fully functional ToDo app using JavaScript. Master CRUD operations, data persistence with LocalStorage, and practical coding techniques in this step-by-step guide.
Welcome back, JavaScript enthusiasts! Today, we’ll tackle an exciting hands-on project—building a simple ToDo app using JavaScript. This exercise will not only reinforce your understanding of core concepts but also give you practical, real-world coding experience. Let’s dive in and create a fully functional ToDo app!
Table of Contents
- Planning and Structuring Your App
- Implementing CRUD Operations
- LocalStorage for Data Persistence
- Wrapping Up
Planning and Structuring Your App
Before diving into the code, it’s essential to plan and structure our ToDo app. The app will consist of three core components:
- An input field for adding new tasks
- A task list to display tasks
- Buttons for editing and deleting tasks
With this structure in mind, we’ll implement the app using HTML, CSS, and JavaScript.
Implementing CRUD Operations
CRUD stands for Create, Read, Update, and Delete—operations essential for managing data in any app. We’ll now implement these features in our ToDo app.
Create
Let’s start by creating an input field and a button to add new tasks. Here’s the HTML:
<input type="text" id="task-input" placeholder="Enter a task"> <button id="add-task-btn">Add Task</button>
Now, we’ll add an event listener to handle creating new tasks when the button is clicked:
/**
* Adds a new task when the button is clicked
* @param {string} taskText - The text for the new task
*/
const taskInput = document.getElementById('task-input');
const addTaskBtn = document.getElementById('add-task-btn');
addTaskBtn.addEventListener('click', () => {
const taskText = taskInput.value.trim();
if (taskText !== '') {
createTask(taskText);
taskInput.value = '';
saveTasks(); // Save to LocalStorage after creating the task
}
});
Read
To display tasks, we’ll use an unordered list:
<ul id="task-list"></ul>
Next, we’ll create a function to display tasks:
/**
* Creates and displays a task
* @param {string} text - The text of the task
*/
const taskList = document.getElementById('task-list');
function createTask(text) {
const listItem = document.createElement('li');
listItem.textContent = text;
addTaskButtons(listItem); // Add edit and delete buttons
taskList.appendChild(listItem);
}
Update and Delete
To update and delete tasks, we’ll add two buttons: one for editing and one for deleting:
/**
* Adds edit and delete buttons to a task
* @param {HTMLElement} listItem - The list item representing the task
*/
function addTaskButtons(listItem) {
const editBtn = document.createElement('button');
editBtn.textContent = 'Edit';
editBtn.addEventListener('click', () => editTask(listItem));
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Delete';
deleteBtn.addEventListener('click', () => deleteTask(listItem));
listItem.appendChild(editBtn);
listItem.appendChild(deleteBtn);
}
/**
* Edits a task
* @param {HTMLElement} listItem - The task item to be edited
*/
function editTask(listItem) {
const updatedText = prompt('Edit the task', listItem.firstChild.textContent);
if (updatedText !== null && updatedText.trim() !== '') {
listItem.firstChild.textContent = updatedText.trim();
saveTasks(); // Save changes to LocalStorage
}
}
/**
* Deletes a task
* @param {HTMLElement} listItem - The task item to be deleted
*/
function deleteTask(listItem) {
if (confirm('Are you sure you want to delete this task?')) {
listItem.remove();
saveTasks(); // Update LocalStorage after deletion
}
}
LocalStorage for Data Persistence
To ensure that tasks persist even after refreshing the page, we’ll use LocalStorage. First, let’s create a function to save tasks:
/**
* Saves tasks to LocalStorage
*/
function saveTasks() {
const tasks = [];
const listItems = taskList.getElementsByTagName('li');
for (let item of listItems) {
tasks.push(item.firstChild.textContent); // Store task text only
}
localStorage.setItem('tasks', JSON.stringify(tasks));
}
We’ll call this function whenever a task is created, updated, or deleted:
// Save tasks after creating a task createTask(taskText); saveTasks(); // Save tasks after editing a task listItem.firstChild.textContent = updatedText.trim(); saveTasks(); // Save tasks after deleting a task listItem.remove(); saveTasks();
Finally, we’ll load the tasks from LocalStorage when the page loads:
/**
* Loads tasks from LocalStorage on page load
*/
function loadTasks() {
const tasks = JSON.parse(localStorage.getItem('tasks'));
if (tasks) {
tasks.forEach(task => createTask(task)); // Re-create tasks on load
}
}
document.addEventListener('DOMContentLoaded', loadTasks); // Load tasks when page loads
Wrapping Up
Here’s the complete code for the ToDo app:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Simple ToDo App</title>
<style>
/* Add your custom styles here */
</style>
</head>
<body>
<h1>Simple ToDo App</h1>
<input type="text" id="task-input" placeholder="Enter a task"/>
<button id="add-task-btn">Add Task</button>
<ul id="task-list"></ul>
<script>
/**
* References to DOM elements for task input and buttons
*/
const taskInput = document.getElementById('task-input');
const addTaskBtn = document.getElementById('add-task-btn');
const taskList = document.getElementById('task-list');
/**
* Event listener to handle adding a new task when the button is clicked
*/
addTaskBtn.addEventListener('click', () => {
const taskText = taskInput.value.trim();
if (taskText) {
createTask(taskText); // Create a new task
saveTasks(); // Save to LocalStorage after task creation
taskInput.value = ''; // Clear input field after task creation
}
});
/**
* Creates a new task list item and adds edit/delete buttons
* @param {string} text - The text of the new task
*/
function createTask(text) {
const listItem = document.createElement('li');
listItem.textContent = text;
addTaskButtons(listItem); // Add Edit and Delete buttons to task
taskList.appendChild(listItem);
}
/**
* Adds Edit and Delete buttons to a task list item
* @param {HTMLElement} listItem - The list item to add buttons to
*/
function addTaskButtons(listItem) {
const editBtn = document.createElement('button');
editBtn.textContent = 'Edit';
editBtn.addEventListener('click', () => editTask(listItem));
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Delete';
deleteBtn.addEventListener('click', () => deleteTask(listItem));
listItem.appendChild(editBtn);
listItem.appendChild(deleteBtn);
}
/**
* Edits the task text after prompting the user
* @param {HTMLElement} listItem - The task list item to edit
*/
function editTask(listItem) {
const updatedText = prompt('Edit the task', listItem.firstChild.textContent);
if (updatedText) {
listItem.firstChild.textContent = updatedText.trim();
saveTasks(); // Save changes after editing the task
}
}
/**
* Deletes a task list item after confirming with the user
* @param {HTMLElement} listItem - The task list item to delete
*/
function deleteTask(listItem) {
if (confirm('Are you sure you want to delete this task?')) {
listItem.remove(); // Remove task from DOM
saveTasks(); // Save the updated task list
}
}
/**
* Saves the current list of tasks to LocalStorage
*/
function saveTasks() {
const tasks = [];
const listItems = taskList.getElementsByTagName('li');
for (let item of listItems) {
tasks.push(item.firstChild.textContent); // Push task text to array
}
localStorage.setItem('tasks', JSON.stringify(tasks)); // Save tasks to LocalStorage
}
/**
* Loads tasks from LocalStorage and displays them on page load
*/
function loadTasks() {
const tasks = JSON.parse(localStorage.getItem('tasks'));
if (tasks) {
tasks.forEach(task => createTask(task)); // Recreate tasks on page load
}
}
// Load tasks from LocalStorage when the document is loaded
document.addEventListener('DOMContentLoaded', loadTasks);
</script>
</body>
</html>
Conclusion
Today’s tutorial walked you through building a simple ToDo app with JavaScript. We covered fundamental concepts like CRUD operations, LocalStorage for data persistence, and DOM manipulation to create, edit, and delete tasks. This practical project serves as an excellent opportunity to reinforce your JavaScript skills with real-world examples.
Remember, the more you practice and experiment with these concepts, the more proficient you will become. Try adding new features like task categories, due dates, or task prioritization to further expand the functionality of your app.
What’s Next?
In Day 9, we’ll explore Regular Expressions in JavaScript. You’ll learn how to match patterns, validate inputs, and manipulate text using powerful regex techniques. Stay tuned for another day of hands-on coding fun!

