by Zafar Saleem
One of the most basic operations in any application is CRUD (stands for Create, Read, Update, Delete). This is something we are going to achieve today. We will take a basic and good old example: a Todo app.
I am assuming that you already have the latest version of node.js on your computer. Setting up our environment is going to take some extra time, so no need to go into these details. Simply clone my boilerplate code from here (https://github.com/zafar-saleem/hut) and run “npm install” to install all the dependencies.
The new files will go into the /src folder. So create a new file called Todo.js inside the /src/scripts/ folder and write the below code into that file.
Now when we create a new instance of this class using the new keyword, the constructor function is automatically called. That is where we will add some attributes to the Todo class which we will be able to access in this entire class using the keyword this.
Now that we have above code, go ahead and import the above file in the src/index.js file and make a new instance of this class like below.
Now we have some basic code in Todo.js. We also need some basic html code. Write the below code in index.html file in the root folder.
Now that we have the basic html code, let’s go back to Todo.js and get the reference to our ‘.list-item’ container. Write the below code inside the constructor.
After getting the reference to “.list-item” element, I am calling the render function to render a list of items on the screen. This function does not exist yet so we are going to write it next.
But before writing the render function, we need some mock data that we are going to render. So for the purpose of this tutorial, we are going to use an array of objects. Write the below code at the top of the Todo.js file.
Now back to the render function: below is the entire render function.
In this function we are making sure that this.list container is empty, that is we do not want any item to be appended to existing items. The first line simply makes the container empty before appending new items.
Next we are looping the mockData array that we created at the top of the Todo.js file using the forEach function. Inside the forEach callback function, we are first creating some DOM elements by calling createDomElements(item.id); function, and we are passing the current item’s id to that function. I will write this function next, but before getting there let’s finish writing this function.
Once it creates the new DOM element (the li element) with child elements (buttons in this case), it adds that li element into the Todo class as an attribute using the “this” keyword. Now we can access that li element throughout the Todo class so I am accessing that li element and adding the title using the insertAdjacentHTML() function.
Next I am checking if the current item is completed or done. If it is, then I add a class to the current li element which adds a line-through style on the item.
And finally I append that li element to this.list.
Now let’s write the createDomElements() function which is below.
This function seems to have plenty of code, but it is simple to understand. I simply create li elements, delete, edit and complete buttons. Then I add some classes to all of these buttons and set the data-id attribute and assign the current item’s id that we passed as an argument from the render function. Then I put text on these buttons (Edit, Delete and Complete) using “innerHTML”.
Finally, I append these buttons to the li element which I later access in the render function to perform further operations.
Now that we have the basic structure, if you run npm run dev and go to localhost:2770 in the browser, you should have the below items, an input field and button, and four items with their respective buttons.
Until now you should have the “R” part of CRUD — I am reading all the elements from mockData and placing them on the screen.
Now that the Read part is done, it is time begin working on the C part of CRUD. Write a function called create and add the below code.
The Create function is pretty self explanatory: all it does is get the value from the text field. It creates a newItem object with attributes ID, title, done and date.
Finally, push that newItem into mockData array and empty the textfield and call the render function to render all the items with the newly created item.
Now go ahead try this in your browser. Put some text in the text field. Press the add button — but you do not see any change. That is expected, because there is still one last part to this. Simply add an event listener to the “add” button inside the constructor and call the create function as below:
Now try it in your browser and voilà. You have the new item at the bottom of the list.
Two parts of the CRUD operations are completed. The next is the D part which is Delete.
This function is also quite simple: first get the id from the delete button element, which was added in the createDomElements function using the data-id attribute. Filter through mockData and place a check on the current item’s id with the delete button’s id. This check simply returns all items except the item this check returns true.
After this operation, re-render all the items by calling the render function at the bottom.
Things are looking good but hold on a minute: this function needs to be triggered by calling the delete button. As you might recall, this button was added dynamically in “createDomElements” function. Adding events to such elements are a little tricky. Since these items were not present when the DOM was loaded and were added later, adding the event listener directly to the delete, update and complete buttons is not going to work.
To make this happen, add the event listener to the document object and find the particular button (“delete” in this case) to perform the delete or remove operation.
To call remove, the self word is used. Inside the callback function, the this keyword loses its reference to the Todo class. For that reason, create a new variable called self and assign the “this” keyword to it at the top of the construction.
Inside the callback function, I check if the click element has a class ‘btn-delete’ — that is, is it a delete button? Then simply trigger the remove function and pass the event as a parameter. I use this inside of the remove function to get the id of the current clicked element to perform the delete operation.
The Update part is slightly complicated. It consists of two functions. The first is to render the edit form, which has a text field and update button. The second is to update the function that performs the update operation.
All the above code does is to add and remove CSS classes to show and hide the edit form which is already in the DOM with the edit-popup class. Get the id from the edit button and place it on the update button. Iterate through mockData and check for the current item using its id. Put the title of the item from mockData into the textfield to edit it.
To trigger this function, follow the same logic for delete to add an event listener, like this:
Now it’s time to write the update operation. Follow the code below:
The first 2 lines of this function are to get the id of the item and value from the text field and put them in their respective variables. Then map through mockData, and place a check to find the item that needs to be updated based on the id. Once that item is found, replace the title with a new “itemTobeUpdate” title. Finally return that updated item from the map.
Once that operation is done, hide the edit-popup form by adding and removing the respective CSS classes. Then re-render mockData by calling the render function.
To trigger this function, add the below code inside the constructor.
Now all CRUD operations have been completed. There is one last step which is not part of CRUD but is part of the Todo app. That is to mark items as completed. The below function will achieve this.
Again, follow the same pattern as the rest of the functions:
- get the id from the button’s data-id attribute
- map through mockData and find the relevant item and set its done property to true and return that item
- finally, re-render mockData by calling the render function.
Again, use the same logic to trigger the delete function, and add the below code inside the constructor to set tasks as completed.
Here is some basic CSS that I used for this tutorial — othing fancy.
To get the code and the complete project, clone below repository: