AngularJS ng-grid filter -- filterText format
Asked Answered
A

2

25

I am using the AngularJS ng-grid (v2.0.7 v2.0.8) and I would like to understand the syntax for the filterText field in the API.

In particular I would like to know how to filter on a specific column or columns, and filter one or more entries in a column.

There are many stack overflow questions with tags ng-grid and filter, and while they are useful, one that gives a full summary of the filterText format is not currently available.

Aldon answered 6/12, 2013 at 21:42 Comment(0)
A
92

At the time of this writing there is no summary on how to construct the 'filterText' string in general. After studying the ng-grid.js code and making some guesses I have found that 'filterText' is much more powerful and expressive than the current documentation suggests.

Example Setup

To set up the answer, first consider a grid with the following definition, located in some controller:

  $scope.pricing_data = data['records'];

  $scope.gridOptions = { 
    data: 'pricing_data',
    columnDefs: [
      { field: 'ticker', displayName: 'Ticker' },
      { field: 'date',   displayName: 'Date'   },
      { field: 'close',  displayName: 'Close'  },
      { field: 'volume', displayName: 'Volume' }
    ],
    filterOptions: {filterText: '', useExternalFilter: false},
    showFilter: true
  };

The object at data['records'] can be some json object sent from the backend. A sample table might look like this:

an unfiltered table

As it stands, filterText is blank so all records are presented.

The down carrot in the upper right of the grid is visible because showFilter is true. Clicking on the down carrot shows an input that is bound to the variable 'filterText'. For this discussion I'll show some results using this dropdown, but generally you can directly assign to filterText in your controller code. The dropdown looks like this:

showFilter widget bound to filterText

Search All Fields in Grid

By default, filterText executes a regex against every cell in the grid. Typing in the character 'a' selects all records that have the character 'a' in any entry (or column) of that record. Typing 'ab' selects all records that have the character sequence 'ab' in any entry of that record. Depending on your requirements, this behavior may be perfectly suitable. However, with large data sets, one typically wants to filter on columns rather than the whole grid because of the nature of the data (e.g. select a price ticker) and because of the high cost of searching the whole grid.

Search By Column

In order to search for a string or regex on just one column, the filterText syntax is:

filterText = '<displayName>:<literal>'

For instance,

first column filter

Here the displayName 'Date' (don't use the field value, you must use displayName) is followed by a colon ':' and then a partial string. The result is that only three records are selected, those associated with Oct 30th.

Let's expand the search. To search for Oct 30th or Oct 31st, the syntax is

filterText = '<displayName>:<literal 1>|<literal 2>|...'

where a pipe '|' separates each string partial. You can chain together however as many as you like. A multi-date filter might look like:

enter image description here

Clearly the selection is OR in nature. My example is not great, however, because tickers and dates have disjoint characters. So you can either trust me that only the Date column is searched or setup your own example. (Or, better still, read the buildSearchConditions() function in ng-grid, its pretty clear on this).

Search Entries in Multiple Columns

Searching multiple columns requires only a syntax extension of the search within a column. This syntax is:

filterText = '<displayName 1>:<lit 1>[|<lit 2>|..];<displayName 2>:<lit a>[|<lit b>|..][;..]'

The operative lexical element is the semicolon ';' that separates each column displayName.

Continuing on with this example, let's search for nyt or nvda on Oct 30th or Oct 31st. That looks like:

multicolumn filter 1

Logically, the filter searches (along Ticker for nyt OR nvda) AND (along Date for 10-30 OR 10-31).

Grid Updates

I am not too familiar with updates that come from cell edits. I suppose that the result is the same.

When the angular-js controller, working in conjunction with the backend, updates the grid data, then the updated data is pushed through the filter. This is a beautiful result, in effect the filter persists.

Known Bug -- Clear

At the time of this writing there is a recent fix to a known bug wherein clearing the filterText nearly or does indeed hang the browser. The report that I've followed is this one: ng-grid issue 777 . A fix was merged following ng-grid issue 848. I can definitely confirm that I see poor performance when a filter applied to a large dataset is cleared. I haven't tested the fix yet.

UPDATE

I just got around to installing ng-grid 2.0.8. The clear problem is fixed afaict. Works great.


ng-grid 3.0

ng-grid 3.0 is on the drawing board now. There is so much goodness in ng-grid 2.0 already, but like any code that's really new, a few rewrites help. I encourage the ng-grid developers to keep the filter features they have already included and perhaps extend the performance or range.

Aldon answered 6/12, 2013 at 21:42 Comment(8)
An excellent answer - I wish it were in the ngGrid Wiki github.com/angular-ui/ng-grid/wiki/Sorting-and-filtering It sorted out one puzzle. My users need to search for strings including colon ':' characters, which happen to be prevalent in my grid's dataset. By modifying the user's search string so that ':' and ';' are replaced with escaped equivalents, like this: filterOptions.filterText = srchTxt.replace(/:/g, "\\x3a").replace(/;/g, "\\x3b"); I was able to fix the problem.Clardy
@JayInNyc Thank you for the answer. One question I have is; is there anyway to do an 'OR' operation rather than 'AND' with multi columns?Honorine
@ChiRow The only reference I have is this answer on SO: #16847178 . They say that filterOptions.filterText cannot be used for OR filters. There are many people who have asked for this. I recommend that you head over to #ng-grid on freenode and make a request. It would be a great feature to add.Aldon
Thanks a lot. One note - for me this worked also using field name instead of displayName. Not sure why, maybe ng-grid has been improved.Pharyngoscope
@Martin Hi Martin. What version are you using? ng-grid does continue to advance. Also, are your fieldNames actually the same as your displayNames? Otherwise it does surprise me a bit, at least for v2.0.8. Then again, I'm hardly surprised by much these days.Aldon
@JayInNyc My column definition is {field:'name', displayName:'Firmas nosaukums'},{field:'registration_number', 'Reģistrācijas numurs'} and when I set filterText to name:a;registration_number:11; it filters data correctly by both conditions. I have ng-grid-2.0.14.Pharyngoscope
@Martin -- ok, great then. Seems like a code change. Thank you for this addition.Aldon
I have forked a Plnkr created by other user, I linked it to ng-grid 2.0.11: plnkr.co/edit/dpTT0RTYpL8wXUav1OgYPharyngoscope
B
9

Based on JayInNyc's answer, I did a few things to make it easier for a user to use instead of following that syntax. I basically watch any fields I want to filter for. In this case I have a input field for the name and city.

$scope.filterOptions = {
    filterText: ''
};
$scope.filterName = '';
$scope.filterCity = '';

$scope.$watch('filterName', function (value) {

    setFilterText();
});

$scope.$watch('filterCity', function (value) {

    setFilterText();
});

function setFilterText()
{
    $scope.filterOptions.filterText = 'Name: ' + $scope.filterName + ';City:' + $scope.filterCity;
}

Btw - I wanted to use the compile function, but it didnt seem to work. I had the following but it didnt work.

filterOptions.filterText = $compile('Name:{{filterName}};Category:{{filterCategory}}')(scope);

Bentley answered 14/4, 2014 at 12:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.