Reputation: 13
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>
Upvotes: 1
Views: 940
Reputation: 43920
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 tr
s 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>
Upvotes: 0
Reputation: 8610
Run an event listener on the main select and if it is checked, get the checked values of the select elements within the table and use a class to set their display to none.
Explanations in code snippit.
Added an option to remove elements from the selected list that are selected while down
is checked.
let down = document.getElementById('down');
let select = document.querySelectorAll('tr input[type="checkbox"]');
function isChecked(e) {
// if event target #down, is checked run over
// each tr select and see which is checked
if (e.target.checked) {
select.forEach(checkBox => {
// toggle classList for select that are NOT checked
// add a helper class to add a display of none
if (!checkBox.checked) {
checkBox.closest('tr').classList.toggle('display-none')
}
})
} else {
// else if #down is not checked, remove all helper class of display none
select.forEach(checkBox => {
checkBox.closest('tr').classList.remove('display-none');
})
}
}
// optional for when you want to remove from the selected list while
// parent #down is selected
// function to remove selected table rows when the main is selected
// and the target select is then unchecked
function removeUnchecked(e) {
if (down.checked && !e.target.checked) {
e.target.closest('tr').classList.add('display-none')
}
}
// event listener for main select #down
down.addEventListener('change', isChecked);
// maybe you remove a tables check on a select while #down select is checked
select.forEach(sel => addEventListener('change', removeUnchecked));
.display-none {
display: none;
}
<div class="parent-container">
<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>
</div>
Upvotes: 0
Reputation: 385
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>
Upvotes: 0
Reputation: 178109
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>
Upvotes: 2