Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply grid filter programmatically from function

Using Ext.ux.grid.FiltersFeature, I have remote filters and I am trying to write a function to apply a date filter on a grid column programmatically (rather than clicking on the filter drop down menu in the column header). The first time I run the function the grid store gets reloaded without the filter. When I run the function a second time (and every time thereafter) it works totally fine, the store reloads with the filters. Here is the gist of the function I have:

// a filter object for testing
aFilter = {type: 'date', field: 'a_date_field', comparison: 'gt', value: '2012-03-08 00:00:00'}

var grid = Ext.create('Ext.grid.Panel', {
    store: store,
    features: [{
        ftype: 'filters',
    }],
    columns[{
        header: 'ID',
        dataIndex: 'id',
        itemId: 'id',            
        width: 40,
    }, {
        xtype: 'datecolumn',
        header: 'Date',
        dataIndex: 'a_date_field',
        itemId: 'a_date_field',
        width: 75,
        format:'j-M-Y',
        filterable: true
    }],
    listeners: {
        'afterrender': function() {

            // Need to create the filters as soon as the grid renders
            // rather than waiting for the user to click on the header
            grid.filters.createFilters();
        }
    },
    bbar: [{
        text: 'Do a filter',
        handler: function() {

            // get the filter that is attached to the grid
            var gridFilter = grid.filters.getFilter(aFilter.field);

            // have to do this to create a menu for this filter
            gridFilter.init({dataIndex: aFilter.field, type: aFilter.type, active: true});

            // if this column is a date filter column
            if (gridFilter.type == 'date') {
                var dateValue = Ext.Date.parse(aFilter.value, 'Y-m-d H:i:s');
                if (filter.comparison == 'gt') {
                    gridFilter.setValue({after: dateValue});
                } else {
                    gridFilter.setValue({before: dateValue});
                }
            }
        }
    }
});

I also found that this function works the first time if I click on any grid header menu before I run the function.

I've been trying to find out what changes are made to the grid which make the filter work after the first attempt fails or what clicking on any grid header does to make it work. But nothing I add seems to fix it so it will run the first time. Has anyone implemented this successfully?

like image 960
egerardus Avatar asked Mar 09 '12 05:03

egerardus


3 Answers

I have workaround:

bbar: [{
    text: 'Do a filter',
    handler: function() {
        var grid = this.up('grid');
        var dateValue = Ext.Date.parse(aFilter.value, 'Y-m-d H:i:s');
        var value = aFilter.comparison == 'gt' ? {after: dateValue} : {before: dateValue};

        var gridFilter = grid.filters.getFilter(aFilter.field);

        if (!gridFilter) {
            gridFilter = grid.filters.addFilter({
                active: true,
                type: aFilter.type,
                dataIndex: aFilter.dataIndex,
            });

            gridFilter.menu.show();
            gridFilter.setValue(value);
            gridFilter.menu.hide();
        } else {
            gridFilter.setActive(true);
        }

        Ext.Function.defer(function(){
            gridFilter = grid.filters.getFilter(aFilter.field);
            gridFilter.setValue(value);
        }, 10);
    }
}]

As you can see I actually apply filter 2 times.

like image 170
Krzysztof Avatar answered Oct 07 '22 16:10

Krzysztof


As an update, I expanded this function and modified it to work with ExtJS 4.1.1

Here is an example of the function to set grid filters dynamically (without the user needing to click on the menu items). Afterwards, the filtered items will be visible to the user in the grid column header menus as if he clicked on them and set them manually.

The "grid" argument is a grid with FiltersFeature that you want to filter. The other argument is an array of "filter" objects (I'll show an example below), the function simply applies all the passed "filter" objects to the grid.

doGridFilter: function(grid, filters) {

    // for each filter object in the array
    Ext.each(filters, function(filter) {
        var gridFilter = grid.filters.getFilter(filter.field);

        gridFilter.setActive(true);
        switch(filter.data.type) {

            case 'date':
                var dateValue = Ext.Date.parse(filter.data.value, 'm/d/Y'),
                    value;

                switch (filter.data.comparison) {

                    case 'gt' :
                        value = {after: dateValue};
                        break;
                    case 'lt' :
                        value = {before: dateValue};
                        break;
                    case 'eq' :
                        value = {on: dateValue};
                        break;
                }
                gridFilter = log.filters.getFilter(filter.field);
                gridFilter.setValue(value);
                gridFilter.setActive(true);
                break;

            case 'numeric':
                var value;

                switch (filter.data.comparison) {

                    case 'gt' :
                        value = {gt: filter.data.value};
                        break;
                    case 'lt' :
                        value = {lt: filter.data.value};
                        break;
                    case 'eq' :
                        value = {eq: filter.data.value};
                        break;
                }
                gridFilter = log.filters.getFilter(filter.field);
                gridFilter.setValue(value);
                gridFilter.setActive(true);
                break;

            case 'list':
                gridFilter = log.filters.getFilter(filter.field);
                gridFilter.menu.setSelected(gridFilter.menu.selected, false);
                gridFilter.menu.setSelected(filter.data.value.split(','), true);
                break;

            default :
                gridFilter = log.filters.getFilter(filter.field);
                gridFilter.setValue(filter.data.value);
                break;
        }
    });
}

Here's an example of a "filter" object array.

// an example of a "filters" argument
[{
    field: 'some_list_column_data_index',
    data: {
        type: 'list',
        value: 'item1,item2,item3,item4,item5,item6,item7'
    }
}, {
    field: 'some_date_column_data_index',
    data: {
        type: 'date',
        comparison: 'gt',
        value: '07/07/2007'
    }
}]

One caveat, you need to "create" the filters manually before using this function. Normally FiltersFeature grid filters are "created" the first time a user clicks on one of them, that may not happen if the user just wants to apply one of these predefined filters.

That can be handled easily by including this afterrender listener in the gridpanel.

listeners: {

    // must create the filters after grid is rendered
    afterrender: function(grid) {
        grid.filters.createFilters();
    }
}
like image 6
egerardus Avatar answered Oct 07 '22 16:10

egerardus


Just add

filter: true

to grid columns description like this:

me.columns = [
        {header:"Name", dataIndex:"name", editor:"textfield", filter: true},
    ];

if you want to get the filter work after the first attempt, first instance create.

like image 3
DShost Avatar answered Oct 07 '22 15:10

DShost