Sunday, June 23, 2013

ExtJs: How to filter data of a store in extjs: A small and useful tutorial

Damn I hate these English summers. It's not summer if it's gonna rain every now and then!
It's disappointing to see a final of a tournament getting washed out and that too when India was looking so invincible. Sigh! (This was when I thought there won't be a match today).


India wins Champions Trophy
India wins Champions Trophy 2013
But guess what, rain stopped and there was a 20 overs match eventually. And India came out victorious in an absolutely spectacular fashion. Great to see them finally lift the cup. They totally deserved it.

Anyways, today I will show you how to set filters on the data of a combobox (or rather any component having a store).
We shall first start with creating simple store containing data for a combobox: 

// The data store containing the list of cars  
 var cars = Ext.create('Ext.data.Store', {  
   autoLoad: true,  
   fields: ['key', 'name'],  
   data: [{  
     "key": "Benz",  
       "name": "Mercedes-Benz"  
   }, {  
     "key": "Audi",  
       "name": "Audi"  
   }, {  
     "key": "Ferrari",  
       "name": "Ferrari"  
   }, {  
     "key": "Prius",  
       "name": "Prius"  
   }, {  
     "key": "Lamborghini",  
       "name": "Lamborghini"  
   }, {  
     "key": "BMW",  
       "name": "BMW"  
   }]  
 });  

Now I will create a combobox and assign the above created store to it.
Note: Here I am creating a toolbar and adding the combobox into it. We will need the filter elements along with the combobox further.

Ext.create('Ext.toolbar.Toolbar', {
    renderTo: document.body,
    items: [{
        xtype: 'combobox',
        fieldLabel: 'Choose Car',
        labelWidth: 70,
        store: cars,
        queryMode: 'local',
        displayField: 'name',
        valueField: 'key'
    }]
}); 

So now you have a combobox displaying all the cars that we have added to the store.
Now let's say we want to add a filter on this data. 
We want two radio buttons, one for BMW and other for Benz. 
If a user selects BMW then only BMW car should be available for selection in the combobox.
And similarly, if he selects Benz then only Mercedes-Benz should be available.
So for this we will first add two radio buttons to our existing toolbar.

 Ext.create('Ext.toolbar.Toolbar', {
    renderTo: document.body,
    items: [{
        xtype: 'combobox',
        fieldLabel: 'Choose Car',
        labelWidth: 70,
        store: cars,
        queryMode: 'local',
        displayField: 'name',
        valueField: 'key'
    }, {
        xtype: 'fieldcontainer',
        fieldLabel: 'Filter',
        defaultType: 'radiofield',
        labelWidth: 40,
        layout: 'hbox',
        items: [{
            boxLabel: 'Benz',
            name: 'size',
            id: 'radio1'
        }, {
            boxLabel: 'BMW',
            name: 'size',
            id: 'radio2'
        }]
    }]
});

Now you have your two radio buttons. But they are not filtering the data as we wanted.
To do that we have to handle the filtering in the radiobutton's change event.

 listeners: {
    change: function (radio2, newvalue, oldvalue) {
 //if the newvalue is true that means the radio button is selected
 if (newvalue) {
  // first clear all the existing filters
  cars.clearFilter();
  // apply filter to the store. Field on which we are filtering is "key"
  cars.filter('key', 'Benz');
        }
    }
}

We just need to add a similar listener to the other radio button as well. 
Everything remains same except for the filter value

cars.filter('key', 'BMW');

What if you need multiple filters like say you want to see both Benz as well as BMW in the dropdown.
Add another radio button which will filter on both Benz and BMW.

{
 boxLabel: 'Both',
 name: 'size',
 id: 'radio3',
 listeners: {
  change: function (radio3, newvalue, oldvalue) {
            if (newvalue) {
    // first clear all existing filters
    cars.clearFilter();
    // use filterBy() to create a customized filter
    cars.filterBy(function (record) {
     // if the key matches either Benz or BMW then return that record
     if (record.get('key') == 'Benz' || record.get('key') == 'BMW') return record;
    });
   }
        }
    }
}

And lastly you will want to clear all your filters and get the original set of records back.
This is easy and if you have noticed it is something which we have already been doing.

{
 boxLabel: 'None',
        name: 'size',
 id: 'radio4',
        listeners: {
  change: function (radio4, newvalue, oldvalue) {
   if (newvalue) {
    // clear all filters.
    cars.clearFilter();
   }
  }
 }
}

There you go.
Now you can apply filter to all your stores

JSFiddle Demo

Hope you guys find this useful.
Please leave your comments and suggestions here.

1 comment:

  1. New Ext.js releases have something that works better especially if you need to do something programmatic: the ChainedStore.

    ReplyDelete