Search code examples
javascripthtml-tableconditional-rendering

Javascript HTML conditional display table of rows looses table column alignment


Hello HTML/Javascript experts,

I need to render large tables (few hundred rows at least) in a browser. In order to help navigating I want to turn on and off sub sets of the rows by check buttons in order to reduce the size of the actually displayed table.

I found two approaches, both unfortunately only working halfways ...

  • using a class attribute per row tag
  • using a JavaScript function toggling the (1) display or (2) visibility members of the elements returned by document.getElementsByClassName()

The problem with the approaches so far is that:

  • (1) modifying display breaks the formatting of the rows
  • (2) modifying visibility does not make the table smaller, just keeps the 'deactivated' rows as blank space

Of course I could modify the table data by removing and re-inserting the rows in question. But my question is:

Does HTML/JavaScript offer a way to modify the sub set of table rows actually displayed and keeping the table formatting intact ?

This is my current code using 2 classes myClass and myOtherClass and the 2 modification techniques using display or visibility

<!DOCTYPE html>
<html>
  <body>
    <script>
      function toggleDisplay(aClass) {
        // console.log("toggleDisplay(" + aClass + ") ...");
        elementsArray = document.getElementsByClassName(aClass);
        [...elementsArray].forEach((element, index, array) => {
          // console.log("toggleDisplay(" + aClass + ") got element:" + element + " display:" + element.style.display + " ...");
          if(element.style.display === '') element.style.display = 'block'
          else element.style.display = element.style.display === 'none' ? 'block' : 'none' 
        }
        );
      }
      function toggleVisibility(aClass) {
        elementsArray = document.getElementsByClassName(aClass);
        [...elementsArray].forEach((element, index, array) => {
          // console.log("toggleVisibility(" + aClass + ") got element:" + element + " visibility:" + element.style.visibility + " ...");
          if(element.style.visibility === '') element.style.visibility = 'visible'
          else element.style.visibility = element.style.visibility === 'hidden' ? 'visible' : 'hidden' 
        }
        );
      }
    </script>
    <style>
table, th, td {
  border: 2px solid;
}
    </style>

    <p>
    <input id="toggleDisplay" type="checkbox" onclick="toggleDisplay('myClass');" >
    <label for="toggleDisplay">toggle myClass display</label>
    <input id="toggleOtherDisplay" type="checkbox" onclick="toggleDisplay('myOtherClass');" >
    <label for="toggleOtherDisplay">toggle myOtherClass display</label>
    </p><p>
    <input id="toggleVisibility" type="checkbox" onclick="toggleVisibility('myClass');" >
    <label for="toggleVisibility">toggle myClass visibility</label>
    <input id="toggleOtherVisibility" type="checkbox" onclick="toggleVisibility('myOtherClass');" >
    <label for="toggleOtherVisibility">toggle myOtherClass visibility</label>
    </p>
    <table>
      <tr><th>X</th><th>Y</th><th>Z</th></tr>
      <tr><td>row1</td><td>A</td><td>B</td></tr>
      <tr class="myClass"><td>row2</td><td>C</td><td>D</td></tr>
      <tr class="myClass myOtherClass"><td>row3</td><td>E</td><td>F</td></tr>
      <tr><td>row4</td><td>G</td><td>H</td></tr>
    </table>
  </body>
</html> 


Solution

  • In your case, you can try using visibility:collapse, which has a special behavior when used with tables (see MDN documentation). Your simplified example is below:

    table,
    th,
    td {
      border: 2px solid;
    }
    
    #toggleVisibility:checked ~ table tr.myClass,
    #toggleOtherVisibility:checked ~ table tr.myOtherClass {
      visibility: collapse
    }
    <input id="toggleVisibility" type="checkbox">
    <label for="toggleVisibility">toggle myClass visibility</label>
    <input id="toggleOtherVisibility" type="checkbox">
    <label for="toggleOtherVisibility">toggle myOtherClass visibility</label>
    
    <table>
      <tr>
        <th>X</th>
        <th>Y</th>
        <th>Z</th>
      </tr>
      <tr>
        <td>row1</td>
        <td>A</td>
        <td>B</td>
      </tr>
      <tr class="myClass">
        <td>long row 2</td>
        <td>C</td>
        <td>D</td>
      </tr>
      <tr class="myClass myOtherClass">
        <td>row3</td>
        <td>E</td>
        <td>F</td>
      </tr>
      <tr>
        <td>row4</td>
        <td>G</td>
        <td>H</td>
      </tr>
    </table>