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.
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.
JavaScript1addButton.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 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.
JavaScript1todoList.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.
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.