Home > Enterprise >  Local storage with jQuery
Local storage with jQuery

Time:07-15

I create a table with CRUD operations in jQuery. All CRUD operations worked, no issues with them. I need to store the every uploaded data in local storage. When I add data to the table, the data is stored in the local storage. But when I added one more data to the table, the first data was deleted automatically in local storage. Local storage displays only current data. If I made any changes to the table, local storage data wouldn't be updated. Please help me to solve the issue.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>CRUD Table jQuery</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>

<body>
    <div >
        <div > 
            <div >
                <input type="button" id="btnAdd"  value="Add New" />
            </div>
        </div>
        <div >
            <div >
                <table id="tblData" >
                    <thead>
                        <tr> 
                            <th>ID</th>
                            <th>Name</th>
                            <th>Address</th>
                            <th>Age</th>
                            <th >Action</th>
                        </tr>
                    </thead>
                    <tbody> 
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    <script>
        var emptyRow = "<tr><td colspan='4' class='text-center'></td></tr>";
        var emptyNewRow = "<tr class='trNewRow'>"; 
        emptyNewRow = emptyNewRow   "    <td class='tdID'>";
        emptyNewRow = emptyNewRow   "        <input type='text' class='form-control txtID' />";
        emptyNewRow = emptyNewRow   "    </td>";
        emptyNewRow = emptyNewRow   "    <td class='tdName'>";
        emptyNewRow = emptyNewRow   "        <input type='text' class='form-control txtName' />";
        emptyNewRow = emptyNewRow   "    </td>";
        emptyNewRow = emptyNewRow   "    <td class='tdAddress'>";
        emptyNewRow = emptyNewRow   "        <input type='text' class='form-control txtAddress' />";
        emptyNewRow = emptyNewRow   "    </td>";
        emptyNewRow = emptyNewRow   "    <td class='tdAge'>";
        emptyNewRow = emptyNewRow   "        <input type='text' class='form-control txtAge' />";
        emptyNewRow = emptyNewRow   "    </td>";
        emptyNewRow = emptyNewRow   "    <td class='tdAction'>";
        emptyNewRow = emptyNewRow   "        <button class='btn btn-sm btn-success btn-save'> Save</button>";
        emptyNewRow = emptyNewRow   "        <button class='btn btn-sm btn-success btn-cancel'> Delete</button>";
        emptyNewRow = emptyNewRow   "    </td>";
        emptyNewRow = emptyNewRow   "</tr>";

        var rowButtons ="<button class='btn btn-success btn-sm btn-edit' > Edit </button>  <button class='btn btn-danger btn-sm' > Delete </button>";
        var rowUpdateButtons ="<button class='btn btn-success btn-sm btn-save' > Update </button>  <button class='btn btn-danger btn-sm btn-save' > Delete </button> ";

        $(document).ready(function () {
            //debugger;
            $("#tblData tbody").append(emptyRow); // adding empty row on page load 
            
            $("#btnAdd").click(function () { 
                //debugger;
                if ($("#tblData tbody").children().children().length == 1) {
                    $("#tblData tbody").html("");
                }
                //debugger;
                $("#tblData tbody").append(emptyNewRow); // appending dynamic string to table tbody
            });
            
            $('#tblData').on('click', '.btn-save', function () {
                const id =  $(this).parent().parent().find(".txtID").val();
                $(this).parent().parent().find(".tdID").html("" id "");

                const name =  $(this).parent().parent().find(".txtName").val();
                $(this).parent().parent().find(".tdName").html("" name ""); 

                const address =  $(this).parent().parent().find(".txtAddress").val();
                $(this).parent().parent().find(".tdAddress").html("" address "");

                const age =  $(this).parent().parent().find(".txtAge").val();
                $(this).parent().parent().find(".tdAge").html("" age "");

                $(this).parent().parent().find(".tdAction").html(rowButtons);
            });
             
            
            $('#tblData').on('click', '.btn-danger', function () { // registering function for delete button  
                $(this).parent().parent().remove();
                if ($("#tblData tbody").children().children().length == 0) {
                    $("#tblData tbody").append(emptyRow);
                }
            });
            

            $('#tblData').on('click', '.btn-cancel', function () { 
                $(this).parent().parent().remove();
            });


            $('#tblData').on('click', '.btn-edit', function () { 

                const id =$(this).parent().parent().find(".tdID").html();
                $(this).parent().parent().find(".tdID").html("<input type='text' value='" id "' class='form-control txtID' />"); 

                const name =$(this).parent().parent().find(".tdName").html();
                $(this).parent().parent().find(".tdName").html("<input type='text' value='" name "' class='form-control txtName' />"); 

                const address =$(this).parent().parent().find(".tdAddress").html();
                $(this).parent().parent().find(".tdAddress").html("<input type='text' value='" address "' class='form-control txtAddress' />"); 

                const age =$(this).parent().parent().find(".tdAge").html();
                $(this).parent().parent().find(".tdAge").html("<input type='text' value='" age "' class='form-control txtAge' />"); 

                $(this).parent().parent().find(".tdAction").html(rowUpdateButtons);
                               
            });

            $('.btn-save').click(function() {
                localStorage.setItem('txtId', id);
                localStorage.getItem('txtId');

                localStorage.setItem('txtName', name);
                localStorage.getItem('txtName');

                localStorage.setItem('txtAddress', address);
                localStorage.getItem('txtAddress');

                localStorage.setItem('txtAge', age);
                localStorage.getItem('txtAge');

            });

            $('.btn-danger').click(function() {
                localStorage.removeItem('txtID');
                localStorage.removeItem('txtName');
                localStorage.removeItem('txtAddress');
                localStorage.removeItem('txtAge');
            });

        });
    </script> 
</body> 
</html>

CodePudding user response:

Consider the following jsFiddle Example. I used jsFiddle as it allows for the use of localStorage where Stack Overflow Snippets do not.

Fiddle: https://jsfiddle.net/Twisty/3u6gpc49/

JavaScript

$(function() {

  var myEmptyRow = [{
    class: "tdID",
    content: $("<input>", {
      type: "text",
      class: "form-control txtID"
    })
  }, {
    class: "tdName",
    content: $("<input>", {
      type: "text",
      class: "form-control txtName"
    })
  }, {
    class: "tdAddress",
    content: $("<input>", {
      type: "text",
      class: "form-control txtAddress"
    })
  }, {
    class: "tdAge",
    content: $("<input>", {
      type: "text",
      class: "form-control txtAge"
    })
  }, {
    class: "tdAction",
    content: [
      $("<button>", {
        class: "btn btn-sm btn-success btn-save"
      }).html("Save"),
      $("<button>", {
        class: "btn btn-sm btn-success btn-cancel"
      }).html("Delete")
    ]
  }];

  var myButtons = {
    edit: [
      $("<button>", {
        class: "btn btn-success btn-sm btn-edit"
      }).html("Edit"),
      $("<button>", {
        class: "btn btn-danger btn-sm"
      }).html("Delete")
    ],
    update: [
      $("<button>", {
        class: "btn btn-success btn-sm btn-save"
      }).html("Update"),
      $("<button>", {
        class: "btn btn-danger btn-sm"
      }).html("Delete")
    ]
  };

  function getStore(index) {
    console.log("Get data for "   index);
    return JSON.parse(localStorage.getItem(index));
  }

  function saveStore(index, data) {
    console.log("Saving Data to "   index, data);
    localStorage.setItem(index, JSON.stringify(data));
  }

  function deleteStore(index) {
    console.log("Deleting Data for "   index);
    localStorage.removeItem(index);
  }

  function addRow(target, data, empty) {
    if (target == undefined) {
      target = $("table:eq(0)");
    }
    if (empty == undefined) {
      empty = false;
    }
    if (data == null) {
      return false;
    }
    console.log("Add Row to "   target.attr("id"), empty);
    if (empty) {
      $("tbody", target).html("");
    }
    var row = $("<tr>").appendTo($("tbody", target));
    if (data == undefined) {
      // Add Empty Row
      $("<td>", {
        colspan: 4,
        class: "text-center"
      }).appendTo(row);
    } else {
      row.addClass("trNewRow");
      $.each(data, function(i, cell) {
        $("<td>", {
          class: cell.class
        }).append(cell.content).appendTo(row);
      });
    }
    console.log(data, data.length);
    if (data.length == 4) {
      $("<td>", {
        class: "tdAction"
      }).append(myButtons.edit).appendTo(row);
    }
    return row;
  }

  function saveRow(row) {
    if (row == undefined) {
      return false;
    }
    var rowData = [{
        class: "tdID",
        content: $(".txtID", row).val()
      },
      {
        class: "tdName",
        content: $(".txtName", row).val()
      }, {
        class: "tdAddress",
        content: $(".txtAddress", row).val()
      }, {
        class: "tdAge",
        content: $(".txtAge", row).val()
      }
    ];

    $.each(rowData, function(i, c) {
      $("."   c.class, row).html(c.content);
    });

    $(".tdAction", row).html(myButtons.edit);

    saveStore("row-"   row.index(), rowData);
  }

  function init() {
    if (localStorage.length == 0) {
      addRow($("#tblData"));
    } else {
      console.log("Found Local Storage. Rows: "   localStorage.length);
      $.each(localStorage, function(k, o) {
        var rowData = getStore(k);
        console.log(k, rowData);
        addRow($("#tblData"), rowData);
      });
    }
  }

  init();

  $("#btnAdd").click(function() {
    addRow($("#tblData"), myEmptyRow, $("#tblData tbody tr td").length == 1 ? true : false);
  });

  $('#tblData').on('click', '.btn-save', function() {
    saveRow($(this).closest("tr"));
  });

  $('#tblData').on('click', '.btn-danger, .btn-cancel', function() {
    // registering function for delete button
    deleteStore("row-"   $(this).closest("tr").index());
    $(this).closest("tr").remove();
    if ($("#tblData tbody tr").length == 0) {
      addRow($("#tblData "));
    }
  });

  $('#tblData').on('click', '.btn-edit', function() {
    var row = $(this).closest("tr");
    $(".tdID", row).html("<input type='text' value='"   $(".tdID", row).html()   "' class='form-control txtID' />");
    $(".tdName", row).html("<input type='text' value='"   $(".tdName", row).html()   "' class='form-control txtName' />");
    $(".tdAddress", row).html("<input type='text' value='"   $(".tdAddress", row).html()   "' class='form-control txtAddress' />");
    $(".tdAge", row).html("<input type='text' value='"   $(".tdAge", row).html()   "' class='form-control txtAge' />");
    $(".tdAction", row).html(myButtons.update);
  });
});

There is a lot to break down here. I will try to focus on the Save, Edit, and Delete buttons. To help with this, it is best to create functions for these operations. Also, you must remember that localStorage can only contain String data.

We will start with Saving a Row. We gather all the details for the Row and then pass them to the saveStore() function. This takes two parameters, an index and the data.

function saveStore(index, data) {
  console.log("Saving Data to "   index, data);
  localStorage.setItem(index, JSON.stringify(data));
}

As we're passing in an Array of Objects, and not a String, we must convert this to a String. I use JSON.stringify() to accomplish this. This results in a JSON String that can be parsed later.

If we are Deleting a row, we can do this.

function deleteStore(index) {
  console.log("Deleting Data for "   index);
  localStorage.removeItem(index);
}

I am using the format row-0, row-1, row-2... for the indexes.

If rows are saved and the browser crashes or the user reloads the page for some reason, you might want to display the currently saved Rows. this is where our final function comes in handy.

function getStore(index) {
  console.log("Get data for "   index);
  return JSON.parse(localStorage.getItem(index));
}

Here we can collect the saved Row data and parse it back into an Array of Objects. Often times, we will know the index name. When we load the page, we may not know the names or how many rows are saved. We can treat localStorage similar to an Object to check on this.

$.each(localStorage, function(k, o) {
  var rowData = getStore(k);
  console.log(k, rowData);
  addRow($("#tblData"), rowData);
});

This iterates over each of the localStore items and gets the index name.

there are a lot of other parts to this that I updated to jQuery. I used what is considered best practices. That might be a matter of opinion, and you can choose to setup your code any way you like. To address this question, please focus on the functions created to help with localStorage.

In regards to your selectors, using .children(), this is not a good method. Consider that $("tr").find(".tdID") is the same as $(".tdID", "tr")

Selector context is implemented with the .find() method; therefore, $( "li.item-ii" ).find( "li" ) is equivalent to $( "li", "li.item-ii" ).

This means that if you can target the parent Row, you can more easily select child elements. Example: $(".tdID", row).html()

CodePudding user response:

localStorage.setItem() does exactly what it suggests... It sets that value to that key in local storage. If any previous value was set, it overwrites that value.

If you want to append to the previous value in some way, you need to read that value, update it, and write it back. For example, this would append the value as an array element:

let txtId = localStorage.getItem('txtId') || [];
txtId.push(id);
localStorage.setItem('txtId', txtId);

(Make sure to clear existing values before debugging this.)

The idea above is to read the stored value, which should be an array if it was previously set. If no value exists, default to an empty array. Then append the new id value to that array. Then write that array back to local storage.

Basically, local storage won't organize your data for you. It will store whatever you write to it and only what you write to it. It's up to you to manage how that data is organized and what you're writing to it.

  • Related