1

I'm using Angular UI grid to show fields.

I have a textbox that user can filter for all columns in the grid. But when the user put text like "(" or "*" is generated a error: Invalid regular expression

Below is the code:

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' ].forEach(function( field ){
        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];
    }
  };
});
.grid {
  width: 500px;
  height: 450px;
}
<!doctype html>
<html ng-app="app">
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-touch.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
    <script src="http://ui-grid.info/release/ui-grid.js"></script>
    <link rel="stylesheet" href="http://ui-grid.info/release/ui-grid.css" type="text/css">
    <link rel="stylesheet" href="main.css" type="text/css">
  </head>
  <body>

<div ng-controller="MainCtrl">
  <input ng-model='filterValue'/><button ng-click='filter()'>Filter</button>
  <div id="grid1" ui-grid="gridOptions" class="grid"></div>
</div>


    <script src="app.js"></script>
  </body>
</html>

Thanks.

1 Answers1

1

You can escape the RegEx input (see the answer to this question for a function that can be used):

str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");

You can then use this bit of code in your $scope.singleFilter function as follows:

$scope.singleFilter = function(renderableRows) {
    var filterVal = undefined;
    if ($scope.filterValue != undefined) {
        // Escape RegEx
        filterVal = $scope.filterValue.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    }
    ...
}

I've created this Fiddle from your code in the question. You'll be able to see from the Fiddle as it is that the Javascript error is no longer generated. As you're only filtering on the 'name', 'company' and 'email' columns, I can't see any data that contains a '(' for example, but if you add the column 'phone' you should be able to see that typing (9 in the filter works.

Community
  • 1
  • 1
Ian A
  • 5,622
  • 2
  • 22
  • 31