Search code examples
javascripthtmlshow-hide

How To Expand Multiple Table <tr> On Single Button Click


I'm trying to create a product comparison table that users can click a button to show/hide additional specification details.

I read you cannot do this with duplicate ids but I've had trouble trying to select by class.

The posted code is my closest attempt thus far.

function toggleTable()
{
 if( document.getElementById("hide").style.display=='none' ){
   document.getElementById("hide").style.display = 'table-row'; // set to table-row instead of an empty string
 }else{
   document.getElementById("hide").style.display = 'none';
 }
}
<h2>Table</h2>
<div>
  <table>
    <tbody>
      <tr>
        <td>Blank</td>
        <td>Info</td>
      </tr>
      <tr>
        <td>Blank</td>
        <td>Info</td>
      </tr>
      <tr id="hide" style="display:none;">
        <td>Show/Hide</td>
        <td>Info</td>
      </tr>
      <tr id="hide" style="display:none;">
        <td>Show/Hide</td>
        <td>Info</td>
      </tr>
    </tbody>
  </table>
</div>
<button type="button" onclick="toggleTable()">Show/Hide ▼</button>

Solution

  • I prefer using classes to identify the parts that will be manipulated - in your case for their display to be toggled - and I keep styles and code out of the html. No inline "onclick" handlers, and style is always in css.

    I removed the id on the rows because it's not needed, and it's illegal to use the same id more than once. I added an id to the button to make it easy to get it in javascript.
    I've also done a little styling so it's easier to see the parts -- the table cells.

    I'm using two classes
    hideable marks the rows that can be hidden or shown - things that are hideable
    hidden because I want to start with those rows already hidden

    The code here gets the "toggle" button using the id I added to it, then adds an event listener to the button for the 'click' event, and I put the code to be run inline rather than making a separate function.

    When the button is clicked it runs the code, which
    • finds all things marked as .hideable
    • toggles the class hidden on each thing found - so if it already has .hidden that is removed and the element becomes visible; if it isn't hidden the .hidden class gets added so the css selector .hideable.hidden sets the display to none.

    document.getElementById('toggle')
      ?.addEventListener('click', (e) => {
          document.querySelectorAll('.hideable')
                  .forEach(h => h.classList.toggle('hidden'));
      });
    table {
      border-collapse: collapse;
      border: 1px solid gray;
    }
    
    th, td {
      padding: 6px;
      border: 1px solid gray;
    }
    
    .hideable {
      display: default;
    }
    
    .hideable.hidden {
      display: none;
    }
    <button type="button" id="toggle">Show/Hide ▼</button>
    <h2>Table</h2>
    <div>
      <table>
        <tbody>
          <tr>
            <td>Blank</td>
            <td>Info</td>
          </tr>
          <tr>
            <td>Blank</td>
            <td>Info</td>
          </tr>
          <tr class="hideable hidden">
            <td>Show/Hide</td>
            <td>Info</td>
          </tr>
          <tr class="hideable hidden">
            <td>Show/Hide</td>
            <td>Info</td>
          </tr>
        </tbody>
      </table>
    </div>