How to Build a To-Do App with Vanilla JavaScript
Creating a to-do app is an excellent way to practice and enhance your JavaScript skills. It’s a beginner-friendly project that covers essential concepts like DOM manipulation, event handling, and local storage. In this blog post, we’ll guide you through how to build a to-do app with vanilla JavaScript. By the end of this tutorial, you’ll have a fully functional app that allows users to add, delete, and mark tasks as complete.
Why Build a To-Do App with Vanilla JavaScript?
Using vanilla JavaScript (without frameworks or libraries) helps you:
- Understand Core Concepts: Learn how JavaScript works under the hood.
- Improve Problem-Solving Skills: Build logic and functionality from scratch.
- Enhance Portfolio: Add a practical project to your portfolio.
- Lightweight App: Avoid unnecessary dependencies for a simple app.
Features of the To-Do App
Our to-do app will include the following features:
- Add Tasks: Users can add new tasks to the list.
- Delete Tasks: Users can remove tasks they no longer need.
- Mark Tasks as Complete: Users can mark tasks as completed.
- Persist Data: Tasks will be saved in the browser’s local storage.
Step-by-Step Guide to Building the To-Do App
1. Set Up the Project
Create a basic HTML file and include a script.js
file for JavaScript and a style.css
file for styling.
<!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="container">
<h1>To-Do App</h1>
<input type="text" id="taskInput" placeholder="Add a new task">
<button id="addTaskBtn">Add Task</button>
<ul id="taskList"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
2. Style the App
Add basic styling to make the app visually appealing.
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 300px;
text-align: center;
}
h1 {
margin-bottom: 20px;
}
input {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
padding: 10px 20px;
background-color: #28a745;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #218838;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid #ccc;
}
li.completed {
text-decoration: line-through;
color: #888;
}
li button {
background-color: #dc3545;
border: none;
color: #fff;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
}
li button:hover {
background-color: #c82333;
}
3. Add JavaScript Functionality
a. Add Tasks
Use JavaScript to add tasks to the list when the user clicks the “Add Task” button.
const taskInput = document.getElementById('taskInput');
const addTaskBtn = document.getElementById('addTaskBtn');
const taskList = document.getElementById('taskList');
addTaskBtn.addEventListener('click', () => {
const taskText = taskInput.value.trim();
if (taskText !== '') {
addTask(taskText);
taskInput.value = '';
saveTasks();
}
});
function addTask(taskText) {
const li = document.createElement('li');
li.textContent = taskText;
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Delete';
deleteBtn.addEventListener('click', () => {
taskList.removeChild(li);
saveTasks();
});
li.appendChild(deleteBtn);
taskList.appendChild(li);
}
b. Mark Tasks as Complete
Add functionality to mark tasks as completed when clicked.
taskList.addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
e.target.classList.toggle('completed');
saveTasks();
}
});
c. Save Tasks to Local Storage
Use local storage to persist tasks even after the page is refreshed.
function saveTasks() {
const tasks = [];
taskList.querySelectorAll('li').forEach(li => {
tasks.push({
text: li.textContent.replace('Delete', '').trim(),
completed: li.classList.contains('completed')
});
});
localStorage.setItem('tasks', JSON.stringify(tasks));
}
function loadTasks() {
const tasks = JSON.parse(localStorage.getItem('tasks')) || [];
tasks.forEach(task => {
const li = addTask(task.text);
if (task.completed) {
li.classList.add('completed');
}
});
}
document.addEventListener('DOMContentLoaded', loadTasks);
Complete JavaScript Code
Here’s the complete JavaScript code for the to-do app:
const taskInput = document.getElementById('taskInput');
const addTaskBtn = document.getElementById('addTaskBtn');
const taskList = document.getElementById('taskList');
// Add Task
addTaskBtn.addEventListener('click', () => {
const taskText = taskInput.value.trim();
if (taskText !== '') {
addTask(taskText);
taskInput.value = '';
saveTasks();
}
});
function addTask(taskText) {
const li = document.createElement('li');
li.textContent = taskText;
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Delete';
deleteBtn.addEventListener('click', () => {
taskList.removeChild(li);
saveTasks();
});
li.appendChild(deleteBtn);
taskList.appendChild(li);
}
// Mark Task as Complete
taskList.addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
e.target.classList.toggle('completed');
saveTasks();
}
});
// Save Tasks to Local Storage
function saveTasks() {
const tasks = [];
taskList.querySelectorAll('li').forEach(li => {
tasks.push({
text: li.textContent.replace('Delete', '').trim(),
completed: li.classList.contains('completed')
});
});
localStorage.setItem('tasks', JSON.stringify(tasks));
}
// Load Tasks from Local Storage
function loadTasks() {
const tasks = JSON.parse(localStorage.getItem('tasks')) || [];
tasks.forEach(task => {
const li = addTask(task.text);
if (task.completed) {
li.classList.add('completed');
}
});
}
document.addEventListener('DOMContentLoaded', loadTasks);
Summary of Features
Feature | Description | Implementation |
---|---|---|
Add Tasks | Users can add new tasks to the list. | addTask() function |
Delete Tasks | Users can remove tasks they no longer need. | Delete button with event listener |
Mark Tasks as Complete | Users can mark tasks as completed. | Toggle completed class on click |
Persist Data | Tasks are saved in local storage. | saveTasks() and loadTasks() functions |
Debugging Tips for Your To-Do App
- Check Console for Errors: Use
console.log()
to debug issues. - Validate Input: Ensure the task input is not empty before adding it.
- Test Local Storage: Verify tasks are saved and loaded correctly.
- Inspect DOM: Use browser developer tools to inspect elements and event listeners.
Enhancements for Future Versions
- Edit Tasks: Allow users to edit existing tasks.
- Due Dates: Add due dates and prioritize tasks.
- Categories: Organize tasks into categories or projects.
- Dark Mode: Add a toggle for dark mode.
Conclusion
Building a to-do app with vanilla JavaScript is a fantastic way to practice core JavaScript concepts and improve your coding skills. By following this tutorial, you’ve created a functional app that allows users to add, delete, and mark tasks as complete, with data persistence using local storage.
This project is a great addition to your portfolio and serves as a foundation for more complex applications. Keep experimenting and adding new features to enhance your app further. Happy coding!
Ready to take your JavaScript skills to the next level? Enroll in our JavaScript Training in Vizag and learn from industry experts!