Lesson 3
Adding and Deleting Todos
Introduction

In this lesson, we will learn how to manage todo items by adding and deleting them in our full-stack todo list application. These functionalities are integral to creating a dynamic and interactive user experience. By leveraging event listeners in JavaScript and understanding the interactions between the front end and back end, we can ensure that user actions are efficiently processed and updated in real-time. This involves handling asynchronous operations to communicate seamlessly with the server, providing a consistent and persistent state for our todo list. Let's dive into the specifics of implementing these core features.

Adding Todos

To add a new todo item to our list, we start by setting up an event listener on the "Add" button. This listener will trigger every time the button is clicked. It's important to validate the input before sending it to the server to prevent adding empty or invalid todos. The event listener ensures that only meaningful entries are processed. Additionally, you should handle any errors that might occur during the network request to provide feedback to the user.

JavaScript
1addButton.addEventListener('click', async () => { 2 const newTodoText = newTodoInput.value.trim(); 3 if (newTodoText) { 4 try { 5 await fetch('/api/todos', { 6 method: 'POST', 7 headers: { 'Content-Type': 'application/json' }, 8 body: JSON.stringify({ text: newTodoText, completed: false }) 9 }); 10 newTodoInput.value = ''; 11 loadTodos(); 12 } catch (err) { 13 console.error('Error adding todo:', err); 14 } 15 } 16});

In the code above, note the use of await before the fetch call. This ensures that the function waits for the POST request to complete before proceeding. By doing this, we guarantee that the new todo item is successfully added to the server before calling loadTodos().

The loadTodos() function is responsible for fetching the updated list of todos from the server. By reloading the todos in this way, we ensure the data remains consistent across the server and client. It prevents scenarios where the client might display outdated or incorrect data. This approach maintains synchronization between the front end and the back end, leading to a reliable user experience.

Deleting Todos

Deleting a todo item involves setting up an event listener on the list (<ul>) itself. This way, we can catch click events on the list items (<li>), and remove the relevant todo when necessary. Using event delegation allows us to handle events on dynamically added elements without needing to attach an event listener to each one. This is more performant and scalable for a growing list. Handling user confirmations using the confirm function adds a layer of safety to prevent accidental deletions. The confirm function displays a dialog box with a specified message and OK/Cancel options. It returns true if the user clicks OK and false if they click Cancel. By using this function before proceeding with a deletion, we ensure that the user genuinely intends to remove the item, reducing the risk of accidental deletions.

JavaScript
1todoList.addEventListener('click', async (e) => { 2 if (e.target.tagName === 'LI' && confirm("Do you want to delete this item?")) { 3 const todoId = e.target.dataset.id; 4 try { 5 await fetch(`/api/todos/${todoId}`, { 6 method: 'DELETE' 7 }); 8 loadTodos(); 9 } catch (err) { 10 console.error('Error deleting todo:', err); 11 } 12 } 13});

In the code above, notice once again the use of await before the fetch call. This ensures the function pauses until the DELETE request is complete. By doing so, we make sure that the todo item is actually removed from the server before proceeding.

It's important to note that HTML tag names are returned as uppercase by default. This is why we use e.target.tagName === 'LI' instead of e.target.tagName === 'li'. Ensuring the correct case is crucial for the condition to evaluate as expected, maintaining compatibility across different browsers.

After the deletion, we call the loadTodos() function to fetch and display the updated list of todos. This approach, just like in the add section, ensures that the client view is always in sync with the server's state. This guarantees data consistency, avoiding discrepancies between what the server holds and what the client displays.

Conclusion

In this lesson, we learned how to add and delete todos using event listeners. These features make our application more dynamic and interactive, allowing users to manage their todo lists effectively. Understanding how to handle user input and manage its state on the server is crucial for developing robust applications. By implementing these operations, you ensure that the user's actions are immediately reflected, leading to a more seamless experience.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.