I have found a great number of questions and answers regarding showing/hiding rows in a table based on checkboxes, but have failed to find an answer that I can get to work for my scenario.
My problem - I have an HTML table where each row has a checkbox that the user can flag if they find that row important. I would like to have a "master" checkbox that toggles the behavior of the table - if master is checked then only show the checked rows on the table, if master is unchecked then show all rows of the table. I need to accomplish this with pure JS, no JQuery.
Any help is greatly appreciated!
Here is some sample HTML code I've been using as a test...
<span class="text-default">
<input type="checkbox" class="down-checkbox" id="down" />
<label for="down">Check to show Flags only</label>
</span>
<table class="table1">
<thead>
<tr>
<th>Flag</th>
<th>No.</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">ONE</span></td>
</tr>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">TWO</span></td>
</tr>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">THREE</span></td>
</tr>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">FOUR</span></td>
</tr>
</tbody>
</table>
Here is an example
const rows = document.querySelectorAll(".table1 tbody tr")
document.getElementById("down").addEventListener("click",function() {
rows.forEach(row => row.hidden = this.checked && !row.querySelector("input").checked)
})
<span class="text-default">
<input type="checkbox" class="down-checkbox" id="down" />
<label for="down">Check to show Flags only</label>
</span>
<table class="table1">
<thead>
<tr>
<th>Flag</th>
<th>No.</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">ONE</span></td>
</tr>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">TWO</span></td>
</tr>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">THREE</span></td>
</tr>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">FOUR</span></td>
</tr>
</tbody>
</table>
Instead of input.parentElement.parentElement to get ancestor <tr> try input.closest('tr') it's less bulkier and easier to read. The dynamic changes to the presentation (not changes to DOM) are .class driven. When #viewFlags is checked .hide is applied to trs that have no checkbox checked and the table is given the .freeze class so no flags can be unchecked when #viewFlags is checked.
const loopRows = (NodeList, hide = false) => {
NodeList.forEach(n => {
if (n.checked && hide) {
n.closest('tr').className = '';
} else if (!n.checked && hide) {
n.closest('tr').className = 'hide';
} else {
n.closest('tr').className = '';
}
})
};
const filterRows = e => {
let chkAll = document.querySelectorAll('.chx');
const vF = e.target;
if (vF.checked) {
vF.closest('table').className = 'freeze';
loopRows(chkAll, true);
} else {
vF.closest('table').className = '';
loopRows(chkAll);
}
};
document.querySelector('#viewFlags').addEventListener('change', filterRows);
.hide {
visibility: hidden
}
.chx+span::before {
content: '\0a\002690';
}
.chx:checked+span::before {
content: '\0a\002691'
}
.freeze .chx {
pointer-events: none;
}
<table>
<thead>
<tr>
<th>
<input id='viewFlags' type="checkbox">
<label type='checkbox'>⛿</label>
</th>
<th>No.</th>
</tr>
</thead>
<tbody>
<tr>
<td><input class='chx' type="checkbox"><span></span></td>
<td>
<div>ONE</div>
</td>
</tr>
<tr>
<td><input class='chx' type="checkbox"><span></span></td>
<td>
<div>TWO</div>
</td>
</tr>
<tr>
<td><input class='chx' type="checkbox"><span></span></td>
<td>
<div>THREE</div>
</td>
</tr>
<tr>
<td><input class='chx' type="checkbox"><span></span></td>
<td>
<div>FOUR</div>
</td>
</tr>
</tbody>
</table>
const downCheckBox = document.querySelector("#down");
const checkBoxes = document.querySelectorAll(".table1 input[type=checkbox]");
downCheckBox.addEventListener("click", () => {
for (checkbox of checkBoxes) {
checkbox.parentNode.parentNode.hidden = downCheckBox.checked && !checkbox.checked;
}
})
<span class="text-default">
<input type="checkbox" class="down-checkbox" id="down" />
<label for="down">Check to show Flags only</label>
</span>
<table class="table1">
<thead>
<tr>
<th>Flag</th>
<th>No.</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">ONE</span></td>
</tr>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">TWO</span></td>
</tr>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">THREE</span></td>
</tr>
<tr>
<td><input type="checkbox" /> </td>
<td><span class="whatever">FOUR</span></td>
</tr>
</tbody>
</table>