When displaying tables, we sometimes want to filter table elements using multiple criteria involving multiple columns. For example, given a table of people that contains information such as their name, age, and transportation method, we might only want to view the people older than 30 that use a bus for transportation. We might also want to filter people by name. To do this, we have to apply multiple filters, such as an age range filter, a multiple-choice filter, and a text filter, to the data at the same time. The easiest way to do this is to make a filter combination function.
We're going to assume that we're using the code from the Creating a sortable paginated table recipe, and we're going to add our filters as described in the previous two recipes. This time we're going to allow for the combination of filters.
Let's modify the previous code to add multiple filters to our table:
We're going to add filter-related inputs to our page after the opening
<body>
tag:<select id="list" style="width:100px;" multiple> </select> Age: <input id="range1" type="text"> to <input id="range2" type="text">, Name: <input type="text" id="name"> <br>
Add the
filter.js
script before the closing</body>
tag:<script type="text/javascript" src="filter.js"></script>
We're going to modify
example.js
to fetch data after the page is loaded and trigger atable:data
event after displaying the data:$(function() { fetchData(function(data) { window.myTable.data = data; setData(data); $("#demo").trigger("table:data"); }); });
Then we can create
filter.js
by combining the code from the previous two recipes:(function() { function getUnique(data, column) { var unique = []; data.forEach(function(row) { if (unique.indexOf(row[column]) < 0) unique.push(row[column]); }); return unique; } function choiceFilter(valueList, col) { return function filter(el) { return valueList.indexOf(el[col]) >= 0; } } function number(n, def) { if (n == '') return def; n = new Number(n); if (isNaN(n)) return def; return n; } function rangeFilter(start, end, col) { var start = number(start, -Infinity), end = number(end, Infinity); return function filter(el) { return start < el[col] && el[col] < end; }; } function textFilter(txt, col) { return function filter(el) { return el[col].indexOf(txt) >= 0; }; } $("#demo").on('table:data', function() { getUnique(window.myTable.data, 4) .forEach(function(item) { $("<option />").attr('value', item) .html(item).appendTo("#list"); }); }); var filters = [null, null, null]; $("#list").change(function() { filters[0] = choiceFilter($("#list").val(), 4); filterAndShow(); }); $("#range1,#range2").on('change keyup', function() { filters[1] = rangeFilter($("#range1").val(), $("#range2").val(), 2); filterAndShow(); }); $("#name").on('change keyup', function() { filters[2] = textFilter($("#name").val(), 1); filterAndShow(); }); function filterAndShow() { var filtered = window.myTable.data; filters.forEach(function(filter) { if (filter) filtered = filtered.filter(filter); }); window.myTable.setData(filtered); }; }());
Like in the previous recipes, we use the Array.filter
function to filter the table. This time we apply multiple filters in succession. We store all of the filter functions in an array.
Whenever there is a change in the inputs, we update the appropriate filter function and rerun filterAndShow()
to display the filtered data.
DataTables is a highly flexible table library with many options and a rich API. More information and examples can be found on the official website at http://www.datatables.net/.