user4809674
user4809674

Reputation: 19

angular ui grid single filter + cellfilter

I have implemented the single filter with ui grid as said in doc. http://ui-grid.info/docs/#/tutorial/321_singleFilter

But I have a cellFilter and when I filter, it filters on data, not rendered data with filter. Which is wrong for end user.

For instance, on this plunker I would like to filter on 'male' or 'female' input.

http://plnkr.co/edit/TNJSlc0QkBI8Tu2Jejam?p=preview

var app = angular.module('app', ['ngTouch', 'ui.grid']);

app.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
  var today = new Date();
  $scope.gridOptions = {
    enableFiltering: false,
    onRegisterApi: function(gridApi){
      $scope.gridApi = gridApi;
      $scope.gridApi.grid.registerRowsProcessor( $scope.singleFilter, 200 );
    },
    columnDefs: [
      { field: 'name' },
      { field: 'gender', cellFilter: 'mapGender' },
      { field: 'company' },
      { field: 'email' },
      { field: 'phone' },
      { field: 'age' },
      { field: 'mixedDate' }
    ]
  };

  $http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
    .success(function(data) {
      $scope.gridOptions.data = data;
      $scope.gridOptions.data[0].age = -5;

      data.forEach( function addDates( row, index ){
        row.mixedDate = new Date();
        row.mixedDate.setDate(today.getDate() + ( index % 14 ) );
        row.gender = row.gender==='male' ? '1' : '2';
      });
    });

  $scope.filter = function() {
    $scope.gridApi.grid.refresh();
  };

  $scope.singleFilter = function( renderableRows ){
    var matcher = new RegExp($scope.filterValue);
    renderableRows.forEach( function( row ) {
      var match = false;
      [ 'name', 'company', 'email', 'gender' ].forEach(function( field ){ 
        //row.entity[field] for gender col is 1 or 2 instead of male or female
        if ( row.entity[field].match(matcher) ){
          match = true;
        }
      });
      if ( !match ){
        row.visible = false;
      }
    });
    return renderableRows;
  };
}])
.filter('mapGender', function() {
  var genderHash = {
    1: 'male',
    2: 'female'
  };

  return function(input) {
    if (!input){
      return '';
    } else {
      return genderHash[input];
    }
  };
});

Upvotes: 1

Views: 1320

Answers (1)

josi
josi

Reputation: 629

There is an option for cells called filterCellFiltered, which you can apply to your columnDefs:

{ field: 'gender', cellFilter: 'mapGender', filterCellFiltered: true },

uiGrid will then apply the cellFilter before applying "search" filters. Unfortunately this option only works for columnFilters. But we can still use it in our singleFilter code to check whether we want to match against the normal or the filtered value.

Not sure if this is the best way to do it, but here is my solution:

  $scope.singleFilter = function( renderableRows ){
    var matcher = new RegExp($scope.filterValue);
    renderableRows.forEach( function( row ) {
      var match = false;
      row.grid.columns.forEach(function( column ){

        // get the filtered value, if filterCellFiltered option is set      
        var value;
        if ( column.filterCellFiltered ){
          value = row.grid.getCellDisplayValue(row, column);
        } else {
          value = row.grid.getCellValue(row, column);
        }

        if ( value.toString().match(matcher) ){
          match = true;
        }
      });

      if ( !match ){
        row.visible = false;
      }
    });
    return renderableRows;
  };

Upvotes: 2

Related Questions