skip to Main Content

I have tables that have hundreds of rows displayed per page, and each row has inputs that can be changed by the user. I want to send only the updated data to the backend so that not too much data will be sent. There is a "save changes" button at the top.

I am not using a form element currently (So to not send the entire table)

What I do is, I give each <tr> the row id from the database as a dataset attribute, and listen to changes on inputs, then if one of the values of a row is changed, I add this entire row and its inputs to an object that holds all the changed rows. This object is then sent to the backend

let updatedData = {};
let table1Form = document.querySelector('#table_1');
table1Form.addEventListener("change", (event) => {
  let row = event.target.closest('tr');
  let rowId = row.dataset.dbRowId;
  let rowInputs = row.querySelectorAll('input');
  updatedData[rowId] = {};
  rowInputs.forEach((input) => {
    if (input.type === "checkbox") {
      updatedData[rowId][input.name] = input.checked;
    } else {
      updatedData[rowId][input.name] = input.value;
    }
  });
});

document.querySelector("#save-changes").addEventListener("click", () => {
  console.log(updatedData);
});
<button id="save-changes">Save Changes</button>
<table id="table_1">
  <tr data-db-row-id="1">
    <td><input type="text" name="email" value="[email protected]" /></td>
    <td><input type="text" name="name" value="Foo" /></td>
    <td><input type="checkbox" name="show" checked="checked" /></td>
  </tr>
  <tr data-db-row-id="2">
    <td><input type="text" name="email" value="[email protected]" /></td>
    <td><input type="text" name="name" value="Bar" /></td>
    <td><input type="checkbox" name="show" /></td>
  </tr>
</table>

But it feels cumbersome, and I need to check for each type of input (in the above example I had to have distinction between the checkbox and the text inputs because they are evaluated differently

Perhaps there’s a better way to do that (with the use of Form Data maybe as well?)

2

Answers


  1. I think a possible solution is saving an instance of the table in an object and when the user clicks on the button you iterate through the new table and check whether the values are the same if not send a request to backend.
    this way i don’t think a checkbox input would be needed.

    Login or Signup to reply.
  2. I am not using a form element currently (So to not send the entire table)

    Don’t know if that is a better way, but in my last project i used something like that, to prevent to submit all data.
    In order not to send the entire form, it just needs to stand alone. The assignment to the form is then done via the form attributes.

    Based on your example:

    <form id="myform" method="POST">
        <input type="submit" value="Save Changes">
    </form>
    <table id="table_1">
      <tr>
        <td><input type="text" name="data[1][email]" value="[email protected]" /></td>
        <td><input type="text" name="data[1][name]" value="Foo" /></td>
        <td><input type="checkbox" name="data[1][show]" checked="checked" /></td>
      </tr>
      <tr>
        <td><input type="text" name="data[2][email]" value="[email protected]" /></td>
        <td><input type="text" name="data[2][name]" value="Bar" /></td>
        <td><input type="checkbox" name="data[2][show]" /></td>
      </tr>
    </table>
    

    Now, you only add the form attribute to the input tags.

    document.querySelector('#table_1').addEventListener("change", (event) => {
      let row = event.target.closest('tr');
      let rowInputs = row.querySelectorAll('input');
      rowInputs.forEach((input) => {
        input.setAttribute('form', 'myform');
      });
    });
    

    Since all browsers except IE understand this, this shouldn’t be a problem.
    https://caniuse.com/form-attribute

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search