Filtering Tables with jQuery

I was recently asked by a friend how you would make a table filterable by using a select box & jQuery - for example "show me films made just in 2014".

Using data attributes I was able to achieve this. Each tr has a data-year attribute which is the value you wish to filter by. This can be anything from a number to a string.

The select box just needs to be the same values.

Lets start with this HTML:

<select>
		<option value="">Please Select</option>
		<option>1997</option>
		<option>1998</option>
		<option>1999</option>
</select>
<table>
		<thead>
			<tr>
					<th>Year</th>
					<th>Version</th>
					<th>Name</th>
			</tr>
		</thead>
		<tbody>
			<tr data-year="1999">
					<td>1999</td>
					<td>Some version Number</td>
					<td>Some Name</td>
			</tr>
			<tr data-year="1997">
					<td>1997</td>
					<td>Some version Number</td>
					<td>Some Name</td>
			</tr>
			<tr data-year="1999">
					<td>1999</td>
					<td>Some version Number</td>
					<td>Some Name</td>
			</tr>
			<tr data-year="1998">
					<td>1998</td>
					<td>Some version Number</td>
					<td>Some Name</td>
			</tr>
		</tbody>
</table>

To filter, hide the rows that don't match the option selected:

$('select').on('change', function(e){
	// Get the value of the select box
	var val = $(this).val();
 // Show all the rows
	$('tbody tr').show();
	// If there is a value hide all the rows except the ones with a data-year of that value
	if(val) {
		$('tbody tr').not($('tbody tr[data-year="' + val + '"]')).hide();
	}
});

The next step was to get it filtering page load - if one of the options was selected.

First step is to add a selected attribute to one of the options

<option selected>1997</option>

Next with the JS - rather than repeat ourselves, we can abstract the logic out into a function and fire that on page load.

var filterTable = function(item) {
	// Get the value of the select box
	var val = item.val();
	// Show all the rows
	$('tbody tr').show();
	// If there is a value hide all the rows except the ones with a data-year of that value
	if(val) {
		$('tbody tr').not($('tbody tr[data-year="' + val + '"]')).hide();
	}
}
$('select').on('change', function(e){
	// On change fire function
	filterTable($(this));
});
// Fire function on load
filterTable($('select'));

This working example can be found on Codepen


The last thing we might want to do is have multiple filters and tables on one page. Again, to save repeating ourselves we can utilise data attributes and store the class of the table we wish to filter on the select box:

<select data-table="test1">

Which reflects the CSS class:

<table class="test1">

This means the tables and select boxes can exist in different parts of the page (if needs be).

The other change to the JS is the page load function, this now grabs all the selects and loops through them - filtering each table in turn:

var filterTable = function(item) {
	// Select the table based on select data attribute
	var table = $('.' + item.data('table') + ' tbody');
	// Cache the table rows
	var rows = table.find('tr');
	// Get the value of the selected item
	var val = item.val();
	// Show all the rows
	rows.show();
	// Hide all the rows except the ones with the value
	if(val) {
		rows.not(table.find('tr[data-year="' + val + '"]')).hide();
	}
}
$('select').on('change', function(e){
	// Fire on select change
	filterTable($(this));
});
// Find all select boxes and loop through to filter
$('select').each(function(i, val){
	filterTable($(val));
});

View this post on Github

You might also enjoy…

Mike Street

Written by Mike Street

Mike is a CTO and Lead Developer from Brighton, UK. He spends his time writing, cycling and coding. You can find Mike on Mastodon.