One of the better starting tasks to learn JavaScript is building a to-do app. This article will create a basic TO-DO app saving task in the LocalStorage on the browser. This means that your tasks persist even if you refresh the website.
LocalStorage: Why is this necessary?
Built-in in the browser feature lets you save data as key-value pairs. This data never expires, hence it stays accessible even after a page refresh or browser restart.
Let us start right now.
Project Structure
To handle our to-do list, we will design a simple HTML structure with JavaScript.
1. HTML Structure
Create an index.html file with this structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To-Do App</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="app">
<h1>To-Do List</h1>
<form id="todo-form">
<input type="text" id="todo-input" placeholder="Add a new task..." required>
<button type="submit">Add</button>
</form>
<ul id="todo-list"></ul>
</div>
<script src="app.js"></script>
</body>
</html>
Code breakdown:
We use a form to insert tasks so the user can press enter to add one.
Input Field: The user cannot submit an empty task since the element needed is required.
Task List: The element holds dynamically the tasks.
Script: We link to a JavaScript that handles all the logic (app.js).
2.Basic CSS
Create a style.css
file to style the app:
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f4f4f4;
}
ul {
list-style-type: none;
padding: 0;
}
.app {
background: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 600px;
}
#todo-form {
display: flex;
align-items: center;
border: 1px solid #ddd;
border-radius: 5px;
overflow: hidden;
}
#todo-form:focus-within {
border-color: #333;
}
button {
background: #333;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
}
#todo-input {
flex: 1;
padding: 10px;
border: none;
outline: none;
}
#todo-list li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid #ddd;
}
button.delete {
background: red;
color: white;
border: none;
padding: 5px 10px;
cursor: pointer;
}
3. JavaScript: Adding Functionality
Create an app.js file.
Choose DOM elements,
First, we need to grab the HTML elements we intend to change with JavaScript:
const todoForm = document.getElementById('todo-form'); const todoInput = document.getElementById('todo-input'); const todoList = document.getElementById('todo-list');
This lets us interact with the form, input field, and task list.
load LocalStorage tasks.
We load tasks from LocalStorage when the application starts to make sure they persist after refreshing.
const todos = JSON.parse(localStorage.getItem('todos')) || [];
localStorage.GetItem('todos') gets the previously saved tasks.
JSON.parse() turns the string back into an array.
If no tasks exist, an empty array returns.
Render current tasks.
Next, we need a function to show the tasks on the screen:
function renderTodos() { // Clear the current list to avoid duplication todoList.innerHTML = ''; // Loop through each todo and create list items todos.forEach((todo, index) => { const li = document.createElement('li'); // Create a new list item li.textContent = todo; // Set the text of the list item to the todo value // Create a delete button for each todo const deleteBtn = document.createElement('button'); deleteBtn.textContent = 'Delete'; // Set button text to 'Delete' deleteBtn.classList.add('delete'); // Add a class to style the button // Add click event to the delete button deleteBtn.addEventListener('click', () => deleteTodo(index)); // Append the delete button to the list item li.appendChild(deleteBtn); // Append the list item to the todo list in the DOM todoList.appendChild(li); }); }
- Why is this stage important? Task appearances won't show without rendering.
- We clean the list to avoid duplicates.
- Each task gets a delete button to click to remove it.
Add New Tasks
When the user submits the form, we need to add the new task to LocalStorage and render it:
function addTodo(e) { e.preventDefault(); // Prevent form from refreshing the page on submit // Get the value from the input and remove whitespace from both ends const newTodo = todoInput.value.trim(); // If the input is empty, do nothing (avoid adding empty tasks) if (newTodo === '') return; // Add the new task to the array of todos todos.push(newTodo); // Save the updated todos array to LocalStorage as a JSON string localStorage.setItem('todos', JSON.stringify(todos)); // Clear the input field after adding the task todoInput.value = ''; // Re-render the task list to include the new task renderTodos(); }
- e.preventDefault() stops the form from page refresh.
- We trim the input and avoid pointless tasks.
- Converting the tasks to a string allows LocalStorage save them.
Delete Tasks
Clicking the delete button should delete the related task.
function deleteTodo(index) { // Remove the todo item from the array at the specified index todos.splice(index, 1); // Update LocalStorage with the new array (after deletion) localStorage.setItem('todos', JSON.stringify(todos)); // Re-render the updated list of tasks renderTodos(); }
Initial Rendering
Now, we call the ā£
renderTodos
function on page load to display saved tasks.renderTodos();
Delete Tasks
Clicking the delete button should delete the related task.
todoForm.addEventListener('submit', addTodo)
This completes the app's core functionality!
View full code and download it on GitHub
Possibly asked questions
Why do we use LocalStorage?
LocalStorage improves user experience by letting tasks remain even after page refreshing, therefore preventing data loss.
How can I store JavaScript tasks to LocalStorage?
JSON.stringify() will transform the task array before it goes to storage; localStorage.setItem() will save tasks as a JSON string.
Can I delete LocalStorage tasks?
Indeed, the splice() method allows us to delete an item from the array, then update LocalStorage and re-render the list.
When the website loads, how can I load LocalStorage tasks?
Retrieve the tasks from localStorage.getitem() and JSON-parse them. Should no tasks exist, create an empty array.
Could the to-do app have more features?
Correct! To grow the app, include task editing, due dates, drag-and-drop capability, and filtering by completed tasks.