ngGrid Multi Column Filtering
Asked Answered
F

1

18

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

Feliciafeliciano answered 30/5, 2013 at 22:12 Comment(3)
I am new to AngularJS, but have gone through all vidoes by johnlindquist / eggheadio / www.egghead.io and I guess this ngfilter video answer your question. He starts to explain how you can use different search filter around 3:00; started with the search across all columns and then moving to specific columns.Exscind
May be this discussion helps you. ng-grid filter per columnBedard
Yes you can implement the filtering through columns with the help of internal filtering option within the grid configuration. I'll put the plunker to it soon with answerPhoton
Y
8

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.

Yarvis answered 24/8, 2013 at 17:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.