One common task when displaying tables is to filter the data in the table to a subset that satisfies a certain criteria. Multiple-choice table filters work on columns with a finite number of values. For example, if we had a table containing data of some people where one column is the transportation method used by the person, the filter used on this column would be a multiple-choice filter. The user should be able to select one or more transportation methods, and the table view would display all the people that are using the selected methods.
We're going to assume that we're using the code and data from the previous recipe. We have a list of people with their transportation methods displayed in a sortable, paginated table using the DataTables jQuery plugin. We will copy the files from the previous recipe, and then add to them.
The data that we need to filter is already available in the tableData
global variable; we can filter this data and then use the global tableSetData
function to display the filtered table.
The filter is going to work on the Transportation field.
Let's modify the previous code to add multiple-choice filters to our table:
In the
index.html
file from the previous recipe, add a multiple-choice select list after the opening<body>
tag:<select id="list" style="width:100px;" multiple> </select>
Add a script element for
filter.js
before the closing</body>
tag:<script type="text/javascript" src="filter.js"></script>
We're also going to modify the
fetchData
call at the end ofexample.js
to trigger a custom event notifying any observers that the data has been fetched and set:$(function() { fetchData(function(result) { window.myTable.data = result.data; setData(result.data); $("#demo").trigger("table:data"); }); });
The code is wrapped to be executed after the page is loaded in order for event triggering to work. Before the page load, no events can be triggered.
Create a file named
filter.js
and add the following code:(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; } } $("#demo").on('table:data', function() { getUnique(window.myTable.data, 4).forEach(function(item) { $("<option />").attr('value', item).html(item).appendTo("#list"); }); }) $("#list").change(function() { var filtered = window.myTable.data.filter( choiceFilter($("#list").val(), 4)); window.myTable.setData(filtered); }); }());
The easiest way to implement a user interface for a multiple-choice filter is to use a multiple-choice select element.
We also need to populate the element when the data becomes available. To do this, we trigger our new custom event table:data
after fetching the data (either from our server or otherwise). The listener extracts the unique values from the Transportation column of the data and populates the select list with options for the values.
When the selection changes, we extract the selected values (as an array) and create a new filter function using choiceFilter
, a higher-order function. The higher-order function returns a new filtering function. This filtering function takes a table row argument and returns true
if the value of the fourth column of that row is contained within the specified list.
The filtering function is passed to Array.filter
; it applies this function to every row and returns an array containing only the rows for which the filtering function returns true
. The filtered data is then displayed instead of the original data.