1

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" />&nbsp;</td>
      <td><span class="whatever">ONE</span></td>
    </tr>
    <tr>
      <td><input type="checkbox" />&nbsp;</td>
      <td><span class="whatever">TWO</span></td>
    </tr>
    <tr>
      <td><input type="checkbox" />&nbsp;</td>
      <td><span class="whatever">THREE</span></td>
    </tr>
    <tr>
      <td><input type="checkbox" />&nbsp;</td>
      <td><span class="whatever">FOUR</span></td>
    </tr>
  </tbody>
</table>

4 Answers 4

2

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" />&nbsp;</td>
      <td><span class="whatever">ONE</span></td>
    </tr>
    <tr>
      <td><input type="checkbox" />&nbsp;</td>
      <td><span class="whatever">TWO</span></td>
    </tr>
    <tr>
      <td><input type="checkbox" />&nbsp;</td>
      <td><span class="whatever">THREE</span></td>
    </tr>
    <tr>
      <td><input type="checkbox" />&nbsp;</td>
      <td><span class="whatever">FOUR</span></td>
    </tr>
  </tbody>
</table>

Sign up to request clarification or add additional context in comments.

Comments

0

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" />&nbsp;</td>
            <td><span class="whatever">ONE</span></td>
        </tr>
        <tr>
            <td><input type="checkbox" />&nbsp;</td>
            <td><span class="whatever">TWO</span></td>
        </tr>
        <tr>
            <td><input type="checkbox" />&nbsp;</td>
            <td><span class="whatever">THREE</span></td>
        </tr>
        <tr>
            <td><input type="checkbox" />&nbsp;</td>
            <td><span class="whatever">FOUR</span></td>
        </tr>
    </tbody>
</table>

1 Comment

checkbox.parentNode.parentNode.hidden is the same as the much safer and easier to read checkbox.closest('tr').hidden
0

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" />&nbsp;</td>
        <td><span class="whatever">ONE</span></td>
      </tr>
      <tr>
        <td><input type="checkbox" />&nbsp;</td>
        <td><span class="whatever">TWO</span></td>
      </tr>
      <tr>
        <td><input type="checkbox" />&nbsp;</td>
        <td><span class="whatever">THREE</span></td>
      </tr>
      <tr>
        <td><input type="checkbox" />&nbsp;</td>
        <td><span class="whatever">FOUR</span></td>
      </tr>
    </tbody>
  </table>
</div>

1 Comment

So overly complicated and non-dry
0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.