the singularity of being and nothingness
ExtJS 4: Filtering on Multiple Fields
Filtering ExtJS data stores is stupid-simple. When filtering, you have 2 main options:
- Filtering on a property (e.g., “field”)
- Filtering with a custom function
Ext.define('Person', { extend: 'Ext.data.Model', idProperty: 'id', fields: [ {'firstname', type:'string'}, {'middlename', type: 'string'}, {'lastname', type: 'string'} ] });
Ext.create('Ext.data.Store', { autoLoad: true, model: 'Person', storeId: 'PersonStore', proxy: { type: 'ajax', url: 'myurl.json', reader: { type: 'json', root: 'people' } } });
var store = Ext.data.StoreManager.lookup('PersonStore'); var peoplefilter = new Ext.util.Filter({ property: 'lastname', value: 'son', anyMatch: true, caseSensitive: false, root: 'data' }); store.filter(peoplefilter);
Nothing to it, right? There are two important parts here. First, for “property”, we are simply specifying the field in our Model which we want to filter on…in this case, “lastname.” Second, we specify that we want the filter to look at the “data” object of each record–otherwise, it will fail miserably 🙂
For simple filtering, using the “property” method will get you by pretty good. For more advanced filtering, however, you’ll need a filter function. A filter function is simply what it sounds like–a custom function that is run against each record. If the function returns true, the record is included in the results, and is excluded otherwise.
So let’s say that we want to only return people whose last names begin with “Mc”. Our filter function might look like this:
var store = Ext.data.StoreManager.lookup('PersonStore'); var peoplefilter = new Ext.util.Filter({ filterFn: function(item) { return item.data.lastname.substr(0, 2)=='Mc' ? true : false } });
While a little different than using the property method, filterFn is very easy to use. You can simply do custom processing on each item, and determine (via returning true or false) whether the record should be part of the filtered set or not. Pretty simple.
Passing Multiple Fields to the Property Filter
Now consider this: you have a larger set of fields in your model, and you want to do something of a wild card search against a number of fields in your model. How would you accomplish this?
Unfortunately, the property filter does not out-of-the-box support passing multiple fields. True enough, you could add 1 filter for each field, but this would leave you with something of an X AND Y AND Z result, instead of the desired X OR Y OR Z result. You could, of course, figure all of this out in a custom filter function. Here’s an example of that:
var searchfilter = new Ext.util.Filter({ Â Â Â filterFn: function(item){ Â Â Â Â Â var searchtest,fnmatch,mnmatch,lnmatch; Â Â Â Â Â var escapere = Ext.String.escapeRegex; searchtest = new RegExp(escapere(search), 'i'); // check match on first name fnmatch = searchtest.test(item.data.firstname); // check match on middelname mnmatch = searchtest.test(item.data.middlename); // check match on name lnmatch = searchtest.test(item.data.lastname); // if any of the fields matched, return true, which will include record in filtered set if(fnmatch || mnmatch || lnmatch) { return true; } // otherwise, return false, which will exclude record from filtered set else { return false; } } })
While not particularly pretty, it works. The main problem is that it more or less duplicates what the property filter is already doing, just a in a bit clunkier way. So instead of doing this, a better approach might be to override the default implementation of Ext.util.Filter. Instead of only allowing for a single property to be evaluated, we’ll beef it up a bit to accept either an array or string of properties.
Ext.override(Ext.util.Filter,{ createFilterFn: function() { var me    = this, matcher = me.createValueMatcher(), property = !Ext.isArray(me.property) ? me.property.split(',') : me.property return function(item) { var hasmatch = false; for(var i=0;i<property.length;i++) { if(matcher.test(me.getRoot.call(me, item)[property[i]])) { hasmatch=true; break; } } return matcher === null ? value === null : hasmatch; }; } })
This is a bit cleaner, IMO. Plus, if we ever need to pass multiple fields to test again, we’ve already got this in place to handle it. Finally, if you compare this to the original, you’ll notice that very little has been changed, and that it’s been designed to work agnostic of whether a single or multiple properties are passed.
Print article | This entry was posted by existdissolve on November 23, 2011 at 6:19 am, and is filed under ExtJS. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |
about 9 years ago
Hello,
I am a beginner in using ExtJs, but keen to learn to use it and have begun to develop a small application. I need to filter the data in a gridPanel after to select a node in a treePanel. After much searching I found this page and I started to follow the examples. The first filter (the simplest) works and I can see it in the console of my browser (GoogleChrome) … I can not to do that the filter result is reflected in my gridPanel. In another examples (working with functions) I simply can’t working with them. I would appreciate help me with an example, especially with the one that can accept more than one search or filter field. Thanks and hopefully I can respond and help.
(sorry for my bad english, I used a translator because I don’t speak english)