I am here again with yet another addition to my 'Getting Started series for FlexGrid'. In my last blog, I talked about common problems faced by various users while implementing it with AngularJS. Today, I will be discussing about Filtering in FlexGrid.

Most of the applications in today's world uses grid to display data and filtering has always been an important feature in it. FlexGrid provides two types of filtering i.e.

  1. Dialog Based Filtering

  2. CollectionView Based Filtering


We already have samples demonstrating how you can implement the above so I won't re-churn the same wheel. The objective of writing this blog is to explain various scenarios wherein you need to use filtering in a different ways. Here are the scenarios which I will be discussing today:

  1. Applying filtering on Multiple columns

  2. Filtering on Columns with Datamap

  3. Multi Value filtering on Single Column

  4. Using both types of Filter on Single Grid


Applying filtering on Multiple Columns


Filtering is generally applied on a single column via CollectionView but there are times when your client wants to search across all the columns which are visible. In this case, we need to check if the respective column is visible or not, get the value and see if it matches the filter or not. The updated filter function will look like:

function applyFilter(item) {
if (!$scope.filter) return true;
var filter = $scope.filter.toLowerCase();
for (var k in item) {
if ($scope.flex.columns.getColumn(k).isVisible) {
var val = item[k];
if (wijmo.isString(val)) {
if (val.toLowerCase().indexOf(filter) >= 0) {
return true;
}
}
}
}
return false;
}

Edit in Fiddle

Applying filtering on Columns with DataMap


DataMap is a very useful feature as it provides the grid with automatic look up capabilities. For example, you may want to display a customer name instead of his ID etc. But, filtering is applied on the key values instead of display values. So, in the above example, filtering will work on ID values and not for customer name.

Nothing to worry though, since we do have a easy work around for implementing the required behavior.  You can make use of the flexible API of FlexGrid. Check if any dataMap exists on a particular column and if so, then get the displayed value for filtering. Here is the code:

function applyFilter(item) {
if (!$scope.filter) return true;
var filter = $scope.filter.toLowerCase();
for (var k in item) {
if ($scope.flex.columns.getColumn(k) != undefined && $scope.flex.columns.getColumn(k).isVisible) {
var val = $scope.flex.columns.getColumn(k).dataMap == undefined ? item[k] : $scope.flex.columns.getColumn(k).dataMap.getDisplayValue(item[k]);
            if (wijmo.isString(val)) {
if (val.toLowerCase().indexOf(filter) >= 0) {
return true;
}
}
}
}
return false;
}

Edit in Fiddle

Multi-Value filtering on Single Column


This is an extension of the default behavior wherein filtering is applied only based on one value. We had a request wherein client wanted to have multi value filter for a single column.

In order to implement it, you have to parse the filter string into words, look for matches against each word, and return true if any matches are found. The changes are:

$scope.cvFilter.filter = function (item) { // ** filter function
// get lowercase version of the country name
var lcc = item.country.toLowerCase();
if ($scope.filter) {
// check for matches against each part of the filter
for (var i = 0; i < lcFilter.length; i++) {
if (lcc.indexOf(lcFilter[i]) > -1) {
return true; // found a match
};
}
return false; // no matches
}
return true; // no filter
};

$scope.$watch('filter', function () { // ** refresh view when filter changes
if (toFilter) {
clearTimeout(toFilter);
}
toFilter = setTimeout(function () {
// split filter into lower-case parts
lcFilter = $scope.filter.toLowerCase().split(' ');
$scope.cvFilter.refresh();
}, 500);
});

Using both types of Filter on Single Grid


As I mentioned initially, FlexGrid provides two types of filtering and many customers want to use both the types of filtering together. By default, when CollectionView based filtering is appllied then dialog based filtering does not work. It is because we are manually defining the filter on the CollectionView, so it overrides the built in filtering.

You can overcome this situation by performing the following steps:

  1. Use 'Raw Data' to create a collection view (CV1)
    - And then filter CV1 using the AngularJS's filter i.e. Collection based Filter

  2. Assign CV1.items (simple array) to grid's itemsSource
    - Grid creates internal collection view (CV2) and Grid filter i.e. Dialog based filter will now act on CV2


Edit in Fiddle

Let me know if you have any other scenario as I will be happy to add it in the above list.