Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngGrid Multi Column Filtering

I am using the ngGrid module for AngularJS to show some paged data. I want to be able to search across multiple columns, however using an OR search.

Lets say I have a column with the following headings: Id, Name, Description. When I search I want to return all rows where either Id OR name OR description contain the search term.

    $scope.pagingOptions = {
        pageSizes: [20, 50, 100],
        pageSize: 20,
        totalServerItems: 0,
        currentPage: 1
    };

    $scope.gridOptions =
        {
            data: 'myData',
            columnDefs: [
                { field: 'id', displayName: 'Id' },
                { field: 'name', displayName: 'Name' },
                { field: 'description', displayName: 'Description' },
                { displayName: 'Actions', cellTemplate: '<input type="button" data-ng-click="doSomething(row.entity)" value="Do Something" />'}],
            enablePaging: true,
            showFooter: true,
            showFilter: true,
            pagingOptions: $scope.pagingOptions,
            filterOptions: {
                filterText: "",
                useExternalFilter: false
            }
        };

I have tried using the default search box, and also using an external input box bound to $scope.filterText to define a custom filter such as:

$scope.filterUpdated = function () {
    $scope.gridOptions.filterOptions.filterText = 'id:' + $scope.filterText + ';name:' + $scope.filterText + ';description:' + $scope.filterText;
};

However this seems to do an AND on all of the columns. Is it possible to achieve what I want using the ngGrid module?

Thanks in advance,

Chris

like image 586
Chris Haines Avatar asked May 30 '13 22:05

Chris Haines


People also ask

How do you enable filters for fields in ag-Grid?

The property can have one of the following values: boolean : Set to true to enable the default filter. The default is Text Filter for AG Grid Community and Set Filter for AG Grid Enterprise. string / Component : Provide a specific filter to use instead of the default filter.

What is agTextColumnFilter?

A Filter Component where you can provide you own filter written in a framework of your choice. If no filter type is specified, the default is 'agTextColumnFilter' for ag-Grid (free versions) and 'agSetColumnFilter' for ag-Grid Enterprise.

How do you get filter data on ag-Grid?

You can use the forEachNodeAfterFilter(callback) api method for this. See https://www.ag-grid.com/javascript-grid-api for all available API calls, including the various forEachXXX methods.

How do you group columns in ag-Grid?

Grouping columns allows you to have multiple levels of columns in your header and the ability, if you want, to 'open and close' column groups to show and hide additional columns. Grouping columns is done by providing the columns in a tree hierarchy to the grid. There is no limit to the number of levels you can provide.


1 Answers

Yes it's possible to do an OR filter, but after searching in the ng-grid source code I can't see how it can be done using their filterOptions.filterText. That can do AND filtering only.

The solution would be then to use filterOptions.useExternalFilter:true

I also found no examples of it, but after playing around with that for a bit, I got the notion that the filter is actually done by re-creating the gridOptions.data object|array. That is the only downside to this filter.

Plunker code is here

So basically your code would look like this index.html:

<body ng-controller="MyCtrl">
  <strong>Filter Name:</strong> </string><input type="text" ng-model="filterName"/>
  </br>
  OR
  </br>
  <strong>Filter Age:</strong> </string><input type="text" ng-model="filterAge"/>
  </br>
  <button ng-click="activateFilter()">Run Filter</button>
  <br/>
  <br/>
  <div class="gridStyle" ng-grid="gridOptions"></div>
</body>

And in your controller.js:

app.controller('MyCtrl', function($scope) {

$scope.filterOptions = {
  filterText: '',
  useExternalFilter: true
};

$scope.activateFilter = function() {
  var name = $scope.filterName || null;
  var age = ($scope.filterAge) ? $scope.filterAge.toString() : null;
  if (!name && !age) name='';

  $scope.myData = angular.copy($scope.originalDataSet, []);
  $scope.myData = $scope.myData.filter( function(item) {
    return (item.name.indexOf(name)>-1 || item.age.toString().indexOf(age) > -1);
  });
 };

 $scope.originalDataSet = [{name: "Moroni", age: 50},
               {name: "Tiancum", age: 43},
               {name: "Jacob", age: 27},
               {name: "Nephi", age: 29},
               {name: "Enos", age: 34}];

 $scope.myData = angular.copy($scope.originalDataSet, []);

 $scope.gridOptions = {
  data: 'myData',
  filterOptions:  $scope.filterOptions
 };
});

That's just basic filtering (use regex and/or convert to lowercase for better matching). Also note that if both name and age are empty I set name to be '' and then every element would return true inside the filter (resulting in the whole dataset return).

This option is much better suited to dynamic dataset (read - server fed), but it works just as well but replicating the original dataset and applying the filters on it.

like image 126
Gilad Peleg Avatar answered Sep 21 '22 07:09

Gilad Peleg