Hide/Show Column in a HTML Table

JqueryHtmlHideHtml TableShow

Jquery Problem Overview


I have an HTML table with several columns and I need to implement a column chooser using jQuery. When a user clicks on a checkbox I want to hide/show the corresponding column in the table. I would like to do this without attaching a class to every td in the table, is there a way to select an entire column using jQuery? Below is an example of the HTML.

<table>
	<thead>
		<tr><th class="col1">Header 1</th><th class="col2">Header 2</th><th class="col3">Header 3</th></tr>
	</thead>
    <tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
    <tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
	<tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
	<tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
</table>

<form>
	<input type="checkbox" name="col1" checked="checked" /> Hide/Show Column 1 <br />
	<input type="checkbox" name="col2" checked="checked" /> Hide/Show Column 2 <br />
	<input type="checkbox" name="col3" checked="checked" /> Hide/Show Column 3 <br />
</form>

Jquery Solutions


Solution 1 - Jquery

One line of code using jQuery which hides the 2nd column:

$('td:nth-child(2)').hide();

If your table has header(th), use this:

$('td:nth-child(2),th:nth-child(2)').hide();

Source: Hide a Table Column with a Single line of jQuery code

jsFiddle to test the code: http://jsfiddle.net/mgMem/1/


If you want to see a good use case, take a look at my blog post:

Hide a table column and colorize rows based on value with jQuery.

Solution 2 - Jquery

> I would like to do this without attaching a class to every td

Personally, I would go with the the class-on-each-td/th/col approach. Then you can switch columns on and off using a single write to className on the container, assuming style rules like:

table.hide1 .col1 { display: none; }
table.hide2 .col2 { display: none; }
...

This is going to be faster than any JS loop approach; for really long tables it can make a significant difference to responsiveness.

If you can get away with not supporting IE6, you could use adjacency selectors to avoid having to add the class attributes to tds. Or alternatively, if your concern is making the markup cleaner, you could add them from JavaScript automatically in an initialisation step.

Solution 3 - Jquery

Here's a little more fully featured answer that provides some user interaction on a per column basis. If this is going to be a dynamic experience, there needs to be a clickable toggle on each column that indicates the ability to hide the column, and then a way to restore previously hidden columns.

That would look something like this in JavaScript:

$('.hide-column').click(function(e){
  var $btn = $(this);
  var $cell = $btn.closest('th,td')
  var $table = $btn.closest('table')

  // get cell location - https://stackoverflow.com/a/4999018/1366033
  var cellIndex = $cell[0].cellIndex + 1;

  $table.find(".show-column-footer").show()
  $table.find("tbody tr, thead tr")
        .children(":nth-child("+cellIndex+")")
        .hide()
})

$(".show-column-footer").click(function(e) {
    var $table = $(this).closest('table')
    $table.find(".show-column-footer").hide()
    $table.find("th, td").show()

})

To support this, we'll add some markup to the table. In each column header, we can add something like this to provide a visual indicator of something clickable

<button class="pull-right btn btn-default btn-condensed hide-column" 
            data-toggle="tooltip" data-placement="bottom" title="Hide Column">
    <i class="fa fa-eye-slash"></i>  
</button>

We'll allow the user to restore columns via a link in the table footer. If it's not persistent by default, then toggling it on dynamically in the header could jostle around the table, but you can really put it anywhere you'd like:

<tfoot class="show-column-footer">
   <tr>
    <th colspan="4"><a class="show-column" href="#">Some columns hidden - click to show all</a></th>
  </tr>
</tfoot>

That's the basic functionality. Here's a demo below with a couple more things fleshed out. You can also add a tooltip to the button to help clarify its purpose, style the button a little more organically to a table header, and collapse the column width in order to add some (somewhat wonky) css animations to make the transition a little less jumpy.

Demo Screengrab

Working Demo in jsFiddle & Stack Snippets:

$(function() {
  // on init
  $(".table-hideable .hide-col").each(HideColumnIndex);

  // on click
  $('.hide-column').click(HideColumnIndex)

  function HideColumnIndex() {
    var $el = $(this);
    var $cell = $el.closest('th,td')
    var $table = $cell.closest('table')

    // get cell location - https://stackoverflow.com/a/4999018/1366033
    var colIndex = $cell[0].cellIndex + 1;

    // find and hide col index
    $table.find("tbody tr, thead tr")
      .children(":nth-child(" + colIndex + ")")
      .addClass('hide-col');
      
    // show restore footer
    $table.find(".footer-restore-columns").show()
  }

  // restore columns footer
  $(".restore-columns").click(function(e) {
    var $table = $(this).closest('table')
    $table.find(".footer-restore-columns").hide()
    $table.find("th, td")
      .removeClass('hide-col');

  })

  $('[data-toggle="tooltip"]').tooltip({
    trigger: 'hover'
  })

})

body {
  padding: 15px;
}

.table-hideable td,
.table-hideable th {
  width: auto;
  transition: width .5s, margin .5s;
}

.btn-condensed.btn-condensed {
  padding: 0 5px;
  box-shadow: none;
}


/* use class to have a little animation */
.hide-col {
  width: 0px !important;
  height: 0px !important;
  display: block !important;
  overflow: hidden !important;
  margin: 0 !important;
  padding: 0 !important;
  border: none !important;
}

<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.7/paper/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>




<table class="table table-condensed table-hover table-bordered table-striped table-hideable">

  <thead>
    <tr>
      <th>
        Controller
        <button class="pull-right btn btn-default btn-condensed hide-column" data-toggle="tooltip" data-placement="bottom" title="Hide Column">
          <i class="fa fa-eye-slash"></i>  
        </button>
      </th>
      <th class="hide-col">
        Action
        <button class="pull-right btn btn-default btn-condensed hide-column" data-toggle="tooltip" data-placement="bottom" title="Hide Column">
          <i class="fa fa-eye-slash"></i>  
        </button>
      </th>
      <th>
        Type
        <button class="pull-right btn btn-default btn-condensed hide-column" data-toggle="tooltip" data-placement="bottom" title="Hide Column">
          <i class="fa fa-eye-slash"></i>  
        </button>
      </th>
      <th>
        Attributes
        <button class="pull-right btn btn-default btn-condensed hide-column" data-toggle="tooltip" data-placement="bottom" title="Hide Column">
          <i class="fa fa-eye-slash"></i>  
        </button>
      </th>
  </thead>
  <tbody>

    <tr>
      <td>Home</td>
      <td>Index</td>
      <td>ActionResult</td>
      <td>Authorize</td>
    </tr>

    <tr>
      <td>Client</td>
      <td>Index</td>
      <td>ActionResult</td>
      <td>Authorize</td>
    </tr>

    <tr>
      <td>Client</td>
      <td>Edit</td>
      <td>ActionResult</td>
      <td>Authorize</td>
    </tr>

  </tbody>
  <tfoot class="footer-restore-columns">
    <tr>
      <th colspan="4"><a class="restore-columns" href="#">Some columns hidden - click to show all</a></th>
    </tr>
  </tfoot>
</table>

Solution 4 - Jquery

you could use colgroups:

<table>
    <colgroup>
       <col class="visible_class"/>
       <col class="visible_class"/>
       <col class="invisible_class"/>  
    </colgroup>
    <thead>
        <tr><th class="col1">Header 1</th><th class="col2">Header 2</th><th class="col3">Header 3</th></tr>
    </thead>
    <tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
    <tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
    <tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
    <tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
</table>

your script then could change just the desire <col> class.

Solution 5 - Jquery

The following should do it:

$("input[type='checkbox']").click(function() {
    var index = $(this).attr('name').substr(2);
    $('table tr').each(function() { 
        $('td:eq(' + index + ')',this).toggle();
    });
});

This is untested code, but the principle is that you choose the table cell in each row that corresponds to the chosen index extracted from the checkbox name. You could of course limit the selectors with a class or an ID.

Solution 6 - Jquery

And of course, the CSS only way for browsers that support nth-child:

table td:nth-child(2) { display: none; }

This is for IE9 and newer.

For your usecase, you'd need several classes to hide the columns:

.hideCol1 td:nth-child(1) { display: none;}
.hideCol2 td:nth-child(2) { display: none;}

ect...

Solution 7 - Jquery

The following is building on Eran's code, with a few minor changes. Tested it and it seems to work fine on Firefox 3, IE7.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<script>
$(document).ready(function() {
    $('input[type="checkbox"]').click(function() {
        var index = $(this).attr('name').substr(3);
        index--;
        $('table tr').each(function() { 
            $('td:eq(' + index + ')',this).toggle();
        });
        $('th.' + $(this).attr('name')).toggle();
    });
});
</script>
<body>
<table>
<thead>
    <tr>
        <th class="col1">Header 1</th>
        <th class="col2">Header 2</th>
        <th class="col3">Header 3</th>
    </tr>
</thead>
<tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
<tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
<tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
<tr><td>Column1</td><td>Column2</td><td>Column3</td></tr>
</table>

<form>
    <input type="checkbox" name="col1" checked="checked" /> Hide/Show Column 1 <br />
    <input type="checkbox" name="col2" checked="checked" /> Hide/Show Column 2 <br />
    <input type="checkbox" name="col3" checked="checked" /> Hide/Show Column 3 <br />
</form>
</body>
</html>

Solution 8 - Jquery

<p><input type="checkbox" name="ch1" checked="checked" /> First Name</p>
.... 
<td class="ch1">...</td>

 <script>
       $(document).ready(function() {
            $('#demo').multiselect();
        });
        
               
        $("input:checkbox:not(:checked)").each(function() {
    var column = "table ." + $(this).attr("name");
    $(column).hide();
});

$("input:checkbox").click(function(){
    var column = "table ." + $(this).attr("name");
    $(column).toggle();
});
 </script>

Solution 9 - Jquery

Without class? You can use the Tag then:

var tds = document.getElementsByTagName('TD'),i;
for (i in tds) {
  tds[i].style.display = 'none';
}

And to show them use:

...style.display = 'table-cell';	    	

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrian FisherView Question on Stackoverflow
Solution 1 - JqueryLeniel MaccaferriView Answer on Stackoverflow
Solution 2 - JquerybobinceView Answer on Stackoverflow
Solution 3 - JqueryKyleMitView Answer on Stackoverflow
Solution 4 - JqueryLuis MelgrattiView Answer on Stackoverflow
Solution 5 - JqueryEran GalperinView Answer on Stackoverflow
Solution 6 - JqueryProblemsOfSumitView Answer on Stackoverflow
Solution 7 - JqueryPaolo BergantinoView Answer on Stackoverflow
Solution 8 - JquerylahbibView Answer on Stackoverflow
Solution 9 - JqueryGustavo RuizView Answer on Stackoverflow