In this final video in the Let's Build a Todo CLI With Node.JS series, you will complete the functionality of the CLI. You will be implementing handler functions to remove and complete todos stored within the JSON file.
- Implement handler functions to complete and remove todos
- Implement the Filter method to exclude specific data from an array
- Implement the Map method to modify a specific element from an array
- Implement with the spread operator to modify object data
- Use the NOT operator to reverse the current value of the todo object’s complete property
- Understand how to use exported functions in another file
This course is intended for anyone who wants to learn about Node.js.
Let's Build a Todo CLI with Node.JS, Part Three. In the previous video, I added the capability to add and view todos to the Todo CLI. In this video, I'm going to add the ability to complete and remove a todo through the CLI. Now, for demonstration purposes, I've already added additional todos to the database. Starting with working inside of the db.js file, I'm going to begin by creating the function to remove a todo. const removeTodo equals an arrow function, and this arrow function will have an argument of id. And this is the id that is attached to the todo.
Next, I need to get all the todos from the todos.json file. So, I will use the getTodos function. getTodos().then, passing in an arrow function with a argument of data. The data argument represents the array of todos from the JSON file. Now, pausing for a moment, I need to use an array method that will remove the todo with the matching id from this existing array. In this use case, I'm going to use the filter method to create a new array that will exclude the todo that matches the id given as an argument. const filteredTodos = data.filter passing in an arrow function with the argument of (todo). The filter method will iterate through the array.
It will loop through the array, and as it loops through, this todo argument represents the current element in the array. As part of the filter methods requirement, I now need to add a condition to filter for. I want to filter for all the todos that have a id property that does not match the id given as a argument. After the arrow, I will write todo.id !== id. So with this conditional, every todo that does not match the argument id will get saved inside of this variable 'filteredTodos' as a new array, excluding the todo with the matching argument id. Because the Todo with the matching argument id has been excluded, this is the equivalent of removing it from the data array. Now that I've created this filteredTodos array, I need to save it to the database using the writeTodos function. writeTodos passing in an argument of filteredTodos. The writeTodos function uses the file systems writeFile method, which will always overwrite the existing file. The end result is a database that no longer has the todo with the matching id argument.
Now, this completes the removeTodo function. I need to export it in order to use it. So, down below, inside of the module exports, I will add removeTodo. Switching over to the todo.Js file, first I need to require the removeTodo. Inside of the structuring, I will write 'removeTodo'. Scrolling down to the Switch statement, under the remove case, I will replace the console log with removeTodo. As a reminder, this todo argument for this use case represents the id that is attached to the todo you wish to remove. Now I'm ready to test out the removeTodo function. Down below in the terminal, to see a list of all the todos, I will type node todo.js view. So, here's a list of five todos. I'm going to remove the first one with the id of 2027. Now I will type the Remove command. node todo.js remove 2027. To verify that the todo has been removed, I will execute the View command again. And in the terminal, the todo with the id of 2027 is no longer there. Now this completes the removeTodo function. I'm going to back to the db.js file and write out the completeTodo function.
Now the completeTodo function is similar to the removeTodo function. const completeTodo equals arrow function with an argument of id. Now just like the previous removeTodo function, I need to get all the todos. getTodos().then, passing in an arrow function with a argument of data. Unlike earlier, I don't need to use the filter method because I'm not removing a todo. I'm just changing the complete property of the todo from false to true, or maybe true to false. I still want to generate a new array of data with this updated information. So, I'm going to use the map method instead. const todos = data.map, passing in an arrow function with the argument of todo.
Just like the filter method, the map method is iterative, and this todo argument represents the current element in the array. Now, in order to find the todo with the matching id, I do need a conditional statement. So, using the if statement, if(todo.id === id). And this approach is the opposite of what I did earlier with the removeTodo function. In this case, I'm looking for the singular todo that has an id that matches the id argument. Now, if the todo id matches I'm going to, and this is the tricky part, return an object using curly brackets, spread operator 'todo', complete: !todo.complete. So, what is happening here is that I'm using the spread operator to unpack the existing todo object. And to the right of the comma, I've included the complete property. And this complete property will replace the existing complete property in the unpacked todo.
So, with the !todo.complete, I'm taking the existing complete value and returning the opposite value using the NOT operator, which is the exclamation point. And this works because the complete property value is a Boolean value, where if it's true, the NOT operator will return false. And if it's false, the NOT operator will return true. And this opposite value will save as part of a new todo object that will be part of the mapped array of todos. So, why use this approach instead of just marking the todo complete property 'true'? This approach allows the user to fix a mistake. If the user marks the wrong todo complete property, they can execute the same CLI command to change the true value to false. Now this handles the todo where the id matches the one that the user wishes to mark complete. What about the todos where the id does not match?
Using an L statement, I will return an object using curly brackets. spread operator 'todo, complete: todo.complete'. Now with this code, I am unpacking the todo and replacing the complete value with the same value. In essence, I'm creating a new object with the same values as before. This doesn't really do anything. And in theory I could have just returned the existing todo, but I wanted to use this as an opportunity to showcase the spread operator.
So, once the map method has finished iterating through the array, the todos variable will hold a new array with the matching todo marked as complete. Just like the removeTodo function that was done earlier in the video, I now need to write the todos passing in an argument of todos. So, this function is ready to export. So, down below, I will add completeTodo to the module.exports. Going back to the todo.js file, I will de-structure completeTodo into the Require statement.
Scrolling down to the Switch statement, I will replace the console.log under the complete case with completeTodo. Now, in the terminal, I will view all the todos, so I can select the todo to mark as complete. node todo.Js view. And here's a list of todos in the terminal. And I'm going to select the todo with the id of 0883. So, now in the terminal, I will type node todo.js complete 0883. I'm going to use the view command again to list out the todos. And the todo with the id of 0883 is now marked true or complete.
Now, what about the edge case where the wrong todo was marked as complete? Well, all that needs to be done is for the Complete command to be run again on the same id to mark it from true to false. In the terminal, I will execute the Complete command using the same id. And now I will view the todos again. And on the screen, the todo with the id 0883 is now marked false, handling the edge case where the wrong Todo was marked as complete. And that's it. This completes the Let's Build a Todo CLI with Node.JS. Thanks for watching @cloudacademy.
Farish has worked in the EdTech industry for over six years. He is passionate about teaching valuable coding skills to help individuals and enterprises succeed.
Previously, Farish worked at 2U Inc in two concurrent roles. Farish worked as an adjunct instructor for 2U’s full-stack boot camps at UCLA and UCR. Farish also worked as a curriculum engineer for multiple full-stack boot camp programs. As a curriculum engineer, Farish’s role was to create activities, projects, and lesson plans taught in the boot camps used by over 50 University partners. Along with these duties, Farish also created nearly 80 videos for the full-stack blended online program.
Before 2U, Farish worked at Codecademy for over four years, both as a content creator and part of the curriculum experience team.
Farish is an avid powerlifter, sushi lover, and occasional Funko collector.