I have a table with three columns: id, price and a checkbox. I want to parse the table to JSON but only include rows with a checked checkbox. However, my code throws Uncaught TypeError: Cannot read properties of undefined (reading 'type')
in this line: if (ele[i].type == 'checkbox' && ele[i].checked == true)
. Where am I going wrong?
const btn = document.getElementById("click");
btn.addEventListener("click", function() {
tableToJson(table);
})
let table = document.getElementById("myTable");
function tableToJson(table) {
let data = [];
const ele = document.querySelectorAll(".myCheckbox");
// first row needs to be headers
let headers = [];
for (i = 0; i < table.rows[0].cells.length; i ) {
headers[i] = table.rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi, '');
}
// go through cells
for (i = 1; i < table.rows.length; i ) {
if (ele[i].type == 'checkbox' && ele[i].checked == true) {
let tableRow = table.rows[i];
let rowData = {};
for (j = 0; j < tableRow.cells.length; j ) {
rowData[headers[j]] = tableRow.cells[j].innerHTML;
}
data.push(rowData);
}
}
console.log(data);
return data;
}
<body>
<button id="click">Click</button>
<table id="myTable">
<thead>
<tr>
<th>Id</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>AAA</td>
<td>12.81</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>BBB</td>
<td>1.06</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>CCC</td>
<td>1.89</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>DDD</td>
<td>1.94</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>EEE</td>
<td>3.61</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
</tbody>
</table>
</body>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
As you're iterating on ele.length
you should use ele[i].type == 'checkbox'
.
Other than that, since you have 5
checkboxes and 6
rows, when you read tableRow
you need to add a 1
otherwise you'll select the wrong row.
In your current code, if you select the first element (index 0) you get the header row (index 0) while you should take index 1 instead.
let tableRow = table.rows[i 1];
const btn = document.getElementById("click");
btn.addEventListener("click", function() {
tableToJson(table);
})
let table = document.getElementById("myTable");
function tableToJson(table) {
let data = [];
const ele = document.querySelectorAll(".myCheckbox");
// first row needs to be headers
let headers = [];
for (i = 0; i < table.rows[0].cells.length; i ) {
headers[i] = table.rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi, '');
}
// go through cells
for (i = 0; i < ele.length; i ) {
if (ele[i].type == 'checkbox' && ele[i].checked == true) {
let tableRow = table.rows[i 1];
let rowData = {};
for (j = 0; j < tableRow.cells.length; j ) {
rowData[headers[j]] = tableRow.cells[j].innerHTML;
}
data.push(rowData);
}
}
console.log(data);
return data;
}
<body>
<button id="click">Click</button>
<table id="myTable">
<thead>
<tr>
<th>Id</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>AAA</td>
<td>12.81</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>BBB</td>
<td>1.06</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>CCC</td>
<td>1.89</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>DDD</td>
<td>1.94</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>EEE</td>
<td>3.61</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
</tbody>
</table>
</body>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
first I do not know where you aré importing your js.
Second javascript Is faster than the dom so by the time you r js gets into if (ele[i].type == 'checkbox' && ele[i].checked == true)
your dom Is not rendered yet. Thats y it breaks you need to wait for your dom to be rendered.
document.addEventLidtener("DOMContentLoaded", e=>{
// Add your code here
});