Building a Dynamic To-Do List Application: A JavaScript Project

Building a Dynamic To-Do List Application: A JavaScript Project

Building a Dynamic To-Do List Application: A JavaScript Project

In this blog, we will bring together the foundational JavaScript concepts you've learned and apply them in a fun, practical project—building a dynamic to-do list application! By the end, you'll have a fully functional app that allows users to add, delete, and track tasks. Let’s break it down step by step.

Step 1: Setting Up Your HTML Structure

Before we dive into the JavaScript code, we need to create the basic structure for the to-do list using HTML. Here's a simple setup:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>To-Do List App</title>
</head>
<body>
    <h1>My To-Do List</h1>
    <input type="text" id="taskInput" placeholder="Add a new task">
    <button id="addTaskBtn">Add Task</button>
    <ul id="taskList"></ul>

    <script src="app.js"></script>
</body>
</html>

In this structure:

  • We have a heading (h1), an input field where the user can type new tasks, a button to add tasks, and an unordered list (ul) to display the tasks.

Step 2: Adding Tasks with JavaScript

Next, we’ll use JavaScript to allow users to add tasks. We’ll start by adding an event listener to the button, so when it’s clicked, the task from the input field will be added to the list.

// Get references to HTML elements
const taskInput = document.getElementById('taskInput');
const addTaskBtn = document.getElementById('addTaskBtn');
const taskList = document.getElementById('taskList');

// Add an event listener to the button
addTaskBtn.addEventListener('click', function() {
    const taskText = taskInput.value;

    if (taskText.trim() !== "") {
        const li = document.createElement('li');
        li.textContent = taskText;
        taskList.appendChild(li);

        // Clear the input field
        taskInput.value = '';
    }
});

Explanation:

  • We first grab the input field, button, and list using document.getElementById.
  • When the "Add Task" button is clicked, we check if the input field is not empty. If it’s not, a new li element (representing a task) is created and added to the list.

Step 3: Deleting Tasks

Now that users can add tasks, let’s give them the ability to delete tasks when they’re done. We’ll modify the event listener to include a delete option for each task.

addTaskBtn.addEventListener('click', function() {
    const taskText = taskInput.value;

    if (taskText.trim() !== "") {
        const li = document.createElement('li');
        li.textContent = taskText;

        // Create a delete button
        const deleteBtn = document.createElement('button');
        deleteBtn.textContent = 'Delete';
        li.appendChild(deleteBtn);

        taskList.appendChild(li);
        taskInput.value = '';

        // Add functionality to delete the task
        deleteBtn.addEventListener('click', function() {
            taskList.removeChild(li);
        });
    }
});

Explanation:

  • For each task (li), we create a "Delete" button using document.createElement('button').
  • We then append this button to the task and add an event listener to remove the task from the list when the button is clicked.

Step 4: Marking Tasks as Complete

Let’s make the app more interactive by allowing users to mark tasks as complete. When a user clicks on a task, we’ll toggle a CSS class that adds a strikethrough effect.

First, let’s add the CSS:

<style>
    .completed {
        text-decoration: line-through;
        color: gray;
    }
</style>

Now, modify the JavaScript to include this feature:

addTaskBtn.addEventListener('click', function() {
    const taskText = taskInput.value;

    if (taskText.trim() !== "") {
        const li = document.createElement('li');
        li.textContent = taskText;

        const deleteBtn = document.createElement('button');
        deleteBtn.textContent = 'Delete';
        li.appendChild(deleteBtn);

        taskList.appendChild(li);
        taskInput.value = '';

        deleteBtn.addEventListener('click', function() {
            taskList.removeChild(li);
        });

        // Mark task as complete when clicked
        li.addEventListener('click', function() {
            li.classList.toggle('completed');
        });
    }
});

Explanation:

  • When a task (li) is clicked, we toggle the .completed class. This class applies a strikethrough effect to indicate that the task is complete.

Step 5: Enhancing the User Experience

To improve the user experience, you might want to consider these additional features:

  • Clear Completed Tasks: Add a button that clears all tasks marked as complete.
  • Persisting Tasks: Use local storage to save tasks even after the page is reloaded.

Here’s how you can implement task persistence using local storage:

// Function to save tasks to localStorage
function saveTasks() {
    const tasks = [];
    taskList.querySelectorAll('li').forEach(function(li) {
        tasks.push({ 
            text: li.firstChild.textContent, 
            completed: li.classList.contains('completed') 
        });
    });
    localStorage.setItem('tasks', JSON.stringify(tasks));
}

// Load tasks from localStorage
function loadTasks() {
    const savedTasks = JSON.parse(localStorage.getItem('tasks') || '[]');
    savedTasks.forEach(function(task) {
        const li = document.createElement('li');
        li.textContent = task.text;
        if (task.completed) {
            li.classList.add('completed');
        }

        const deleteBtn = document.createElement('button');
        deleteBtn.textContent = 'Delete';
        li.appendChild(deleteBtn);
        taskList.appendChild(li);

        deleteBtn.addEventListener('click', function() {
            taskList.removeChild(li);
            saveTasks();
        });

        li.addEventListener('click', function() {
            li.classList.toggle('completed');
            saveTasks();
        });
    });
}

// Initialize the app
loadTasks();

addTaskBtn.addEventListener('click', function() {
    const taskText = taskInput.value;

    if (taskText.trim() !== "") {
        const li = document.createElement('li');
        li.textContent = taskText;

        const deleteBtn = document.createElement('button');
        deleteBtn.textContent = 'Delete';
        li.appendChild(deleteBtn);

        taskList.appendChild(li);
        taskInput.value = '';

        deleteBtn.addEventListener('click', function() {
            taskList.removeChild(li);
            saveTasks();
        });

        li.addEventListener('click', function() {
            li.classList.toggle('completed');
            saveTasks();
        });

        saveTasks();
    }
});

Explanation:

  • We use localStorage to store tasks and their status (completed or not).
  • When the page loads, tasks are loaded from localStorage, and any changes (adding, deleting, marking as complete) are automatically saved.

Conclusion

Congratulations! You've built a fully functional to-do list application using HTML, CSS, and JavaScript. This project is a fantastic way to practice key JavaScript concepts like event handling, DOM manipulation, and local storage. Try experimenting further by adding features like task editing or categories.

Happy coding!

Author: Aryan Kumar is a web developer specializing in HTML, CSS, and JavaScript, working at Asecurity. Contact here (Instagram) : @aryan_geek .

#webdevelopment #html #css #javascript