DEV Community

Cover image for Building CRUD with ES6 JavaScript and Local Storage
Roselle Tabuena
Roselle Tabuena

Posted on

Building CRUD with ES6 JavaScript and Local Storage

In this tutorial, we'll learn how to create a basic CRUD application using JavaScript ES6 and Local Storage. By the end of this guide, you'll know how to implement CRUD with local storage in your own projects. Let's get code together.

Prerequisites:

Basic knowledge in the following:
HTML
Javascript
CSS

Set up

File Structure:

Set up your file first with your choosen IDE.

index.css
index.html 
index.js
Enter fullscreen mode Exit fullscreen mode

Inital Code

CSS

Copy this CSS code into your index.css.

HTML

Copy this index.html into your index.css.

JavaScript

We're utilizing the dialog as our modal, so we don't have to code the modal manually. Simply copy the code below into your index.js.

const dialog = document.querySelector('dialog');
const showButton = document.querySelector('#btn-add');
const closeButton = document.querySelector('#btn-close');

showButton.addEventListener('click', () => {
  dialog.showModal();
});

closeButton.addEventListener('click', () => {
  dialog.close();
});
Enter fullscreen mode Exit fullscreen mode

Exploring our Initial App:

Since our focus is to build a small application using JavaScript and localStorage as our database, we'll skip the HTML part and dive directly into explaining how we will build the functionality.

Let's explore our app first. Click the "Add Student" and see the form with fields name, email and course.

html form with name, email, course fields

Now, let's move on to the table display. You'll notice the following columns:

  • ID: Unique identification of the student data
  • Name, Email, Course: Personal Info of the student
  • Actions: Perform Edit and Delete record in this columns

Since you already know what our app. Let's start to code.

START

Copy this code first; we'll use it later. Make sure it's positioned below your main code for better organization.

/* Modal dialog code */

/* put your code here... */


// utilities 
function populateTable() {
  let tableRow = '';
  getStudentList().forEach((student) => {
    tableRow += tableRowHTML(student);
  });

  table.innerHTML = tableRow;
}

const generateRandomId = () => Math.floor(Math.random() * 99999);

const formDataToObject = (formData) => {
  const object = {};
  formData.forEach((value, key) => {
    object[key] = value;
  });
  return object;
};

function resetForm() {
  document.querySelector('#student-id').value = '';
  studentForm.reset();
}

function tableRowHTML(student) {
  return `<tr id='std_${student.id}'>
            <td>${student.id}</td>
            <td>${student.name}</td>
            <td>${student.email}</td>
            <td>${student.course}</td>
            <td class="actions">
            <button student-id="${student.id}" action-type="edit" class="edit-btn">Edit</button>
            <button student-id="${student.id}" action-type="delete" class="delete-btn">Delete</button>
            </td>
        </tr>`;
}

function getStudentList() {
  return JSON.parse(localStorage.getItem('studentList')) || [];
}
Enter fullscreen mode Exit fullscreen mode

Declarations:

// dialog code 

const studentForm = document.getElementById('student-form');
const table = document.querySelector('table tbody');
Enter fullscreen mode Exit fullscreen mode

Getting the studentForm and table from our DOM, we'll add event listeners later.

CREATE

Add Form Function

const addForm = (formData) => {
  formData.append('id', generateRandomId());

  const student = formDataToObject(formData);
  studentList.push(student);

  localStorage.setItem('studentList', JSON.stringify(studentList));

  const newRow = table.insertRow(-1);

  newRow.id = 'std_' + student.id;
  newRow.innerHTML = tableRowHTML(student);
};
Enter fullscreen mode Exit fullscreen mode

The function above, addForm, adds new student data to the application. It generates a random ID for the student, appends it to the form data, and converts the form data into a student object. The student object is then added to the studentList array, which is stored in local storage. Additionally, a new row is inserted into the HTML table to display the new student's information.

FORM SUBMISSION:
addSubmit function to the form.

studentForm.addEventListener('submit', (event) => {
  event.preventDefault();

  const formData = new FormData(studentForm);

  addForm(formData);

  resetForm();
  dialog.close();
});
Enter fullscreen mode Exit fullscreen mode

To test if it's working, go to the localStorage in the inspect tab under the "Application" section, and check if the data has been added successfully. If it's working, proceed to the next step.

READ

We have a function called populateTable. Its purpose is to display the existing data in the localStorage during the first load of our application. It retrieves data from the getStudentList() function.

Call populateTable() after all the our variable declarations.

const studentForm = document.getElementById('student-form');
const table = document.querySelector('table tbody');

populateTable(); // add this code
Enter fullscreen mode Exit fullscreen mode

This will display the student info on the first load of the application if there's an existing data.

UPDATE

Displaying Student Information in a Modal for Editing.

table.addEventListener('click', (event) => {
  const target = event.target;
  const id = target.getAttribute('student-id');

  if (target.classList.contains('edit-btn')) {
    dialog.showModal();

    const student = getStudentList().find((student) => id == student.id);

    document.getElementById('student-id').value = student.id;
    document.getElementById('name').value = student.name;
    document.getElementById('email').value = student.email;
    document.getElementById('course').value = student.course;
  }
});

Enter fullscreen mode Exit fullscreen mode

The code snippet above enables editing of student details directly within the table. When a user clicks an edit button in a row, it triggers a dialog displaying the student's information fetched from the getStudentList() function based on the student ID. The data retrieved is then utilized to update the input values for each field using document.getElementById('input-id').

EDIT

const editForm = (formData) => {
  const studentForm = formDataToObject(formData);
  const studentList = getStudentList();

  const studentIndex = getStudentList().findIndex(
    (student) => studentForm.id == student.id
  );

  if (studentIndex == -1) return;

  studentList[studentIndex] = {
    ...studentList[studentIndex],
    ...studentForm,
  };

  localStorage.setItem('studentList', JSON.stringify(studentList));

  document.querySelector('#std_' + studentForm.id).innerHTML =
    tableRowHTML(studentForm);
};
Enter fullscreen mode Exit fullscreen mode

The editForm function edits student details by updating the student list with new form data and saving it back to local storage. It first converts form data to an object, retrieves the student list, finds the index of the student being edited, updates their information using tableRowHTML, and then updates the corresponding row in the HTML table with the new data.

FORM SUBMISSION:

studentForm.addEventListener('submit', (event) => {
  event.preventDefault();

  const formData = new FormData(studentForm);

  const isEditMode = formData.get('id') != ''; 

  if (isEditMode) {
    editForm(formData);
  } else {
    addForm(formData);
  }

  resetForm();
  dialog.close();
});

Enter fullscreen mode Exit fullscreen mode

We've improved our form to handle both updating and adding student data using just one form. Now, if the form has an id field, it's for editing, so we call the editForm function. Otherwise, if there's no id field, it's for adding new data, so we call the addForm function. This tweak makes it easier for users to manage student information in our application.

DELETE

table.addEventListener('click', (event) => {
  const target = event.target;
  const id = target.getAttribute('student-id');

  if (target.classList.contains('edit-btn')) {... code for edit ...}
  } else if (target.classList.contains('delete-btn')) {
    const row = target.parentNode.parentNode;
    const newStudentList = getStudentList().filter(
      (student) => id != student.id
    );

    document.querySelector('table').deleteRow(row.rowIndex);

    localStorage.setItem('studentList', JSON.stringify(newStudentList));
}); 

Enter fullscreen mode Exit fullscreen mode

Let's modify our code for table.addEventListener(). We've added a new condition for the delete button if it's triggered. Then, we'll retrieve the row of the table using target.parentNode.parentNode. Afterward, we'll use filter to return a new list without the student ID of the selected student item in the table. Following this, we'll delete the selected row using deleteRow. Lastly, we'll update the new localStorage with our new student list. This functionality allows our users to delete user records directly from the table interface while keeping the data synchronized.

END OF CODE

That's all for the CRUD functionality. I hope you found this tutorial helpful. If you encounter any issues, feel free to refer to our source code for comparison. I also include the demo link below so you can test the application yourself.

CLICK HERE FOR DEMO
INITAL CODE
CRUD SOURCE CODE

Thank you for reading my blog.

If you have any suggestions or corrections, please leave a comment below. I'll gladly respond and consider your input.

Top comments (3)

Collapse
 
artydev profile image
artydev • Edited

Very nice, thank you :-)
The next step could be to save it in a Google Sheet...

Collapse
 
iamdete profile image
Roselle Tabuena

Yeah, that's a great idea! We could add an export button and convert the list into a spreadsheet. ^_^

Collapse
 
artydev profile image
artydev

Yes :-)
If you don't want to expose the GoogleSheet part on the frontend, you can implement it using napkin, in Javascript or in Python