How can I retrieve the IDs for the changes selected through a checkbox?

Viewed 64

I'm having a problem in retrieving only the ids of the selected row via a checkbox in my table where the elements are dynamically created.

In the code below I have put only the one of interest.

Specifically I get the following error:

Cannot read properties of null (reading 'textContent')

.
.
.
  let child = document.createElement("tr");
  child.innerHTML = `
                    <td>${item.id}</td>
                    <td><img src=articoli_img/${item.image} width="150" heigth="150"></td> 
                    td>${item.date}</td>
                    <td>${'<input type="checkbox" id="myCheck">'}</td>`;
  table.appendChild(child);
})
}
};

function retrieveID() {
  var cbs = document.querySelectorAll('#my-table input[type="checkbox"]:checked');
  console.log(cbs.length);
  const ids = Array.from(cbs).map(cb => cb.closest('td').nextElementSibling.textContent);
  console.log(ids);
}
<table id="my-table" width="90%">
  <tr>
    <th>Id</th>
    <th>Image</th>
    <th>Date</th>
    <th>Check</th>
  </tr>

</table>

<br><br>

<input type="button" value="GetID" onclick="retrieveID()" />

Can you kindly help me?

3 Answers

You can simply store the id in a attribute of the checkbox:

  child.innerHTML = `... <td>${`<input type="checkbox" id="myCheck" data-item-id="${item.id}">`}</td>`;
// ...
  const ids = Array.from(cbs).map((cb) => cb.getAttribute("data-item-id"));

which will make your code look like this:

let table = document.getElementById("my-table");

const Items = [
  {
    id: 1,
    image: "test1.jpg",
    date: "2020-01-01",
  },
  {
    id: 2,
    image: "test2.jpg",
    date: "2020-01-02",
  },
  {
    id: 3,
    image: "test3.jpg",
    date: "2020-01-03",
  },
];

Items.forEach(function (item) {
  let child = document.createElement("tr");
  child.innerHTML = `
    <td>${item.id}</td>
    <td><img src="articoli_img/${item.image}" width="150" heigth="150"></td> 
    td>${item.date}</td>
    <td>${`<input type="checkbox" id="myCheck" data-item-id="${item.id}">`}</td>`;
  table.appendChild(child);
});

function retrieveID() {
  var cbs = document.querySelectorAll(
    '#my-table input[type="checkbox"]:checked'
  );
  console.log(cbs.length);
  const ids = Array.from(cbs).map((cb) => cb.getAttribute("data-item-id"));
  console.log(ids);
}
<table id="my-table" width="90%">
  <tr>
    <th>Id</th>
    <th>Image</th>
    <th>Date</th>
    <th>Check</th>
  </tr>

</table>

<br><br>

<input type="button" value="GetID" onclick="retrieveID()" />

You have a lot of small errors in your code. i have rewritten your code a little bit. so that you are able to read out the clicked rows. you can then pull the data from the tr element yourself.

let table = document.getElementById("my-table");
let allart = [];
allart['Items'] = [{id: 1, image: 'xx', date: 2022}]
console.log(allart['Items'][0].id)
allart.Items.forEach(function(item) {
  let child = document.createElement("tr");
  child.setAttribute("id", "data-" +item.id);
  child.innerHTML = `
                    <td>${item.id}</td>
                    <td><img src=articoli_img/${item.image} width="150" heigth="150"></td> 
                    <td>${item.date}</td>
                    <td><input type="checkbox" data-ref="${item.id}" id="myCheck"></td>`;
  table.appendChild(child);
})


//xmlhttp.open("GET", url, true);
//xmlhttp.send();


function retrieveID() {
  var cbs = document.querySelectorAll('#my-table input[type="checkbox"]:checked');
  console.log(cbs.length);
  console.log(cbs[0])
  let col = [];
  cbs.forEach(c => {
    let id = c.getAttribute('data-ref');
    let data = document.querySelector('#data-' + id)
    console.log(data)
    // do something
  })    
}
<table id="my-table" width="90%">
  <tr>
    <th>Id</th>
    <th>Image</th>
    <th>Date</th>
    <th>Check</th>
  </tr>
</table>

<br><br>

<input type="button" value="GetID" onclick="retrieveID()" />

I would suggest that you rework your solution somewhat: do not use the selected state directly from the DOM (HTML). Instead, update the dataset based on an event handler that reacts to some user event.

The snippet below does this:

  • stores the checked state in the Items
  • the checked state is updated when the checkbox change event fires
  • when you get the IDs, it's simply a filter of the Items array.

Also, I updated your example as there were some errors.

const table = document.querySelector("#my-table tbody");
const btnGetId = document.getElementById('get-id')
/*.
.
.*/
const allart = {
  Items: [{
      id: 'id1',
      image: 'fakeImage1',
      date: Date.now(),
      checked: false,
    },
    {
      id: 'id2',
      image: 'fakeImage2',
      date: Date.now(),
      checked: false,
    },
  ],
}

allart.Items.forEach(function(item) {
  let child = document.createElement("tr");
  child.innerHTML = `
    <td>${item.id}</td>
    <td><img src="articoli_img/${item.image}" width="150" heigth="150"></td> 
    <td>${item.date}</td>
    <td><input type="checkbox" data-itemid="${item.id}"/></td>`;
  table.appendChild(child);
})
// }
// };

// reacting to selection
const updateChecked = (id, items) => {
  return items.map(item => {
    if (id === item.id) {
      return {
        ...item,
        checked: !item.checked
      }
    }
    return item
  })
}

// adding event handlers to the checkboxes
const cbs = document.querySelectorAll('tr input[type="checkbox"]')
cbs.forEach(cb => {
  cb.addEventListener('change', function(e) {
    const id = e.target.getAttribute("data-itemid")
    allart.Items = updateChecked(id, allart.Items)
  })
})

// xmlhttp.open("GET", url, true);
// xmlhttp.send();

// updating the event handler on GetId click
btnGetId.addEventListener('click', function() {
  const selectedItems = retrieveId(allart.Items)
  // here you have the items that are selected
  // you can use all the data it has
  console.log(selectedItems)
})

// returning the items that are selected
function retrieveId(items) {
  return items.filter(({ checked }) => checked)
}
<table id="my-table" width="90%">
  <thead>
    <tr>
      <th>Id</th>
      <th>Image</th>
      <th>Date</th>
      <th>Check</th>
    </tr>
  </thead>
  <tbody></tbody>
</table>
<br><br>
<input id="get-id" type="button" value="GetID" />

Related