9

In ExtJs, there are many options to filter a grid. There are two nice examples in the documentation, like referenced in this question.

  1. Remote filtering
  2. Local filtering

However, having the filter hidden in the default dropdown menu of Ext.ux.grid.FiltersFeature looks really awkward for me. A good ergonomic choice would to create search fields in the column headers, like @Ctacus shows in his question.

How can this be achieved ?

Community
  • 1
  • 1
Lorenz Meyer
  • 19,166
  • 22
  • 75
  • 121

1 Answers1

24

After quite much research through the sparse documentation, and thanks to great questions and answers in SO, I came up with a simple class, that adds this functionality and and allows for configurations.

It looks like this:

Search filter fields in column header

You add this field in your grid like this:

Ext.define('Sandbox.view.OwnersGrid', {
    extend: 'Ext.grid.Panel',
    requires: ['Sandbox.view.SearchTrigger'],
    alias: 'widget.ownersGrid',
    store: 'Owners',
    columns: [{
        dataIndex: 'id',
        width: 50,
        text: 'ID'
    }, {
        dataIndex: 'name',
        text: 'Name',
    items:[{
        xtype: 'searchtrigger',
        autoSearch: true
    }]
},

The following configs are possible, and work like described in the doc for Ext.util.Filter:

  • anyMatch
  • caseSensitive
  • exactMatch
  • operator
  • additionnaly you can use autoSearch. If true, the filter searches as you type, if false or not set, one has to click on the search icon to apply the filter.

ExtJs 5 / 6 Source:

Ext.define('Sandbox.view.SearchTrigger', {
    extend: 'Ext.form.field.Text',
    alias: 'widget.searchtrigger',
    triggers:{
        search: {
            cls: 'x-form-search-trigger',
            handler: function() {
                this.setFilter(this.up().dataIndex, this.getValue())
            }
        },
        clear: {
            cls: 'x-form-clear-trigger',
            handler: function() {
                this.setValue('')
                if(!this.autoSearch) this.setFilter(this.up().dataIndex, '')
            }
        }
    },
    setFilter: function(filterId, value){
        var store = this.up('grid').getStore();
        if(value){
            store.removeFilter(filterId, false)
            var filter = {id: filterId, property: filterId, value: value};
            if(this.anyMatch) filter.anyMatch = this.anyMatch
            if(this.caseSensitive) filter.caseSensitive = this.caseSensitive
            if(this.exactMatch) filter.exactMatch = this.exactMatch
            if(this.operator) filter.operator = this.operator
            console.log(this.anyMatch, filter)
            store.addFilter(filter)
        } else {
            store.filters.removeAtKey(filterId)
            store.reload()
        }
    },
    listeners: {
        render: function(){
            var me = this;
            me.ownerCt.on('resize', function(){
                me.setWidth(this.getEl().getWidth())
            })
        },
        change: function() {
            if(this.autoSearch) this.setFilter(this.up().dataIndex, this.getValue())
        }
    }
})

For ExtJs 6.2.0, the following bug and its workaround is relevant to this, else the column cannot be flexed.

ExtJs 4 Source:

Ext.define('Sandbox.view.SearchTrigger', {
    extend: 'Ext.form.field.Trigger',
    alias: 'widget.searchtrigger',
    triggerCls: 'x-form-clear-trigger',
    trigger2Cls: 'x-form-search-trigger',
    onTriggerClick: function() {
        this.setValue('')
        this.setFilter(this.up().dataIndex, '')
    },
    onTrigger2Click: function() {
        this.setFilter(this.up().dataIndex, this.getValue())
    },
    setFilter: function(filterId, value){
        var store = this.up('grid').getStore();
        if(value){
            store.removeFilter(filterId, false)
            var filter = {id: filterId, property: filterId, value: value};
            if(this.anyMatch) filter.anyMatch = this.anyMatch
            if(this.caseSensitive) filter.caseSensitive = this.caseSensitive
            if(this.exactMatch) filter.exactMatch = this.exactMatch
            if(this.operator) filter.operator = this.operator
            console.log(this.anyMatch, filter)
            store.addFilter(filter)
        } else {
            store.filters.removeAtKey(filterId)
            store.reload()
        }
    },
    listeners: {
        render: function(){
            var me = this;
            me.ownerCt.on('resize', function(){
                me.setWidth(this.getEl().getWidth())
            })
        },
        change: function() {
            if(this.autoSearch) this.setFilter(this.up().dataIndex, this.getValue())
        }
    }
})
Community
  • 1
  • 1
Lorenz Meyer
  • 19,166
  • 22
  • 75
  • 121
  • I was able to implement your code in my ExtJS Grid. One of the problem is sometimes the user cannot switch between the searchTrigger fields in columns using mouse click. Also 'Tab' key works for switching between searchTriggers. Do you experience the same issue? – vinay Apr 30 '14 at 17:40
  • I found that sometines, I cannot access the serach field with a mouse click, but I didn't look further, and I didn't recognize any pattern on when that problem occurs. – Lorenz Meyer Apr 30 '14 at 18:04
  • Ok. Thank you. I am trying to fix it. Sometimes on mouse click the 'focus' event is not fired at all and the search field is not accessible. Its random, sometimes it works and sometimes it doesnt. I will continue troubleshooting it, Let me know if you find something. – vinay Apr 30 '14 at 18:16
  • possible to add combo field in this filter? – Dharmesh Hadiyal Feb 03 '15 at 06:40
  • @DharmeshHadiyal Sure you can filter a column with a combo box in it's header. Instead of extending the `SearchTrigger` form `Ext.form.field.Trigger` you would have to extend it from `Ext.form.field.ComboBox` and adapt the code a little. – Lorenz Meyer Feb 03 '15 at 07:02
  • if possible then please give small example – Dharmesh Hadiyal Feb 03 '15 at 08:09
  • @DharmeshHadiyal Take the code above and adapt it for your needs. I cannot do your work in your place. Thanks for your understanding. – Lorenz Meyer Feb 03 '15 at 08:17
  • 1
    for those, who are using extjs5, triggerCls and trigger2Cls should be replaced with Ext.form.field.Text triggers, see here http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/#!/api/Ext.form.field.Text-cfg-triggers – fen1ksss Feb 19 '15 at 08:24
  • @fen1ksss Thanks for this precision. I'll switch to ExtJs 5.0 soon. – Lorenz Meyer Feb 19 '15 at 08:38
  • While I was Implementing it in Extjs 5 ,TextField is not taking space in between the value (ex:- 'Form Field').If I paste the value It filters it but while typing it doesnot take the space. Any idea??? – Abhinav Bhardwaj Mar 09 '15 at 12:12
  • @yellen It needs some tweaks to work with 5.1. I did not yet migrate, so I cannot give the code yet. – Lorenz Meyer Apr 23 '15 at 17:54
  • 2
    For ExtJS 5.1: http://dev.sencha.com/ext/5.1.0/examples/kitchensink/#grid-filtering Not so intuitive, but it works and it's official. – Marco Sulla Apr 12 '16 at 12:46
  • 1
    Not Work for me. ExtJS 6.0.2. No errors, but no search fields are displayed. – Magno C Jan 04 '17 at 11:58
  • Searching is working fine but resize of filter is not working.For Example if we resize Name column Filter is not resizing automatically.Is anyone having idea how to achieve this? – Bhagwat Gurle Jan 17 '17 at 09:21
  • Can someone reproduce code in **Sencha Fiddle** on **6.2.0**?https://stackoverflow.com/questions/46631002/filter-in-grid-header-extjs-6 – Slava Mokerov Oct 08 '17 at 12:56