从函数以编程方式应用网格过滤器

时间:2012-03-09 05:48:50

标签: extjs filter grid extjs4

使用Ext.ux.grid.FiltersFeature,我有远程过滤器,我正在尝试编写一个函数来以编程方式在网格列上应用日期过滤器(而不是单击列标题中的过滤器下拉菜单)。第一次运行该函数时,网格存储在没有过滤器的情况下重新加载。当我第二次运行该功能(以及之后每次)它完全正常工作时,商店会重新加载过滤器。以下是我所拥有的功能的要点:

// 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});
                }
            }
        }
    }
});

我还发现,如果在运行该函数之前单击任何网格标题菜单,此函数将首次运行。

我一直试图找出对网格做了哪些更改,这使得过滤器在第一次尝试失败后工作,或者点击任何网格标题使其工作。但是我添加的任何东西似乎都没有解决它所以它会第一次运行。有没有人成功实现过这个?

7 个答案:

答案 0 :(得分:9)

我有解决方法:

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);
    }
}]

如您所见,我实际上应用过滤器2次。

答案 1 :(得分:6)

作为更新,我扩展了此功能并对其进行了修改以使用ExtJS 4.1.1

以下是动态设置网格过滤器的功能示例(无需用户点击菜单项)。之后,过滤的项目将在网格列标题菜单中对用户可见,就像他点击它们并手动设置它们一样。

“网格”参数是您想要过滤的FiltersFeature网格。另一个参数是“过滤器”对象的数组(我将在下面显示一个示例),该函数只是将所有传递的“过滤器”对象应用于网格。

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;
        }
    });
}

以下是“过滤器”对象数组的示例。

// 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'
    }
}]

有一点需要注意,在使用此功能之前,您需要手动“创建”过滤器。通常FiltersFeature网格过滤器是在用户第一次点击其中一个时“创建”的,如果用户只想应用其中一个预定义过滤器,则可能不会发生这种情况。

通过在网格面板中包含此Afterrender侦听器,可以轻松处理。

listeners: {

    // must create the filters after grid is rendered
    afterrender: function(grid) {
        grid.filters.createFilters();
    }
}

答案 2 :(得分:3)

添加

filter: true

到这样的网格列描述:

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

如果您想在第一次尝试后获得过滤器,则首先创建实例。

答案 3 :(得分:1)

这是值得研究的事情。似乎过滤器插件正在侦听menucreate事件以初始化过滤器。我想知道菜单创建事件是否延迟到必要,因此过滤器不会被初始化?

/**
 * @private Handle creation of the grid's header menu. Initializes the filters and listens
 * for the menu being shown.
 */
onMenuCreate: function(headerCt, menu) {
    var me = this;
    me.createFilters(); //<------
    menu.on('beforeshow', me.onMenuBeforeShow, me);
},

答案 4 :(得分:0)

你想应用网格过滤器还是store.filter()能力更适合你?在这种情况下,只需过滤商店,网格将显示过滤后的记录。

答案 5 :(得分:0)

我发现了另一种实现这个的方法。在渲染网格后,网格特征似乎仅绑定到网格。这意味着在渲染网格之前,过滤器的任何设置都不会生效。商店的初始加载似乎是在呈现网格之前启动的。

我通过使用不包含数据的内存代理创建商店来解决我的问题。

me.store = Ext.create('Ext.data.Store', {
    model: 'SummaryData',
    data: [],
    proxy: {
        type: 'memory',
        reader: 'array'
    },
    remoteSort: true,
    remoteFilter: true
});

然后在网格上设置afterrender处理程序以查找正确的代理并启动商店的加载。

afterrender: function () {
    var me = this;

    me.store.setProxy({
        type: 'ajax',
        url : '/print_unallocated/change_site__data',
        reader: {
            type: 'json',
            root: 'rows'
        },
        listeners: {
            exception: function (proxy, response) {
                Max.reportException(response);
            }
        }
    });

    me.filters.createFilters();
    me.store.load();
},

答案 6 :(得分:0)

在源代码中,您可以看到与此相关的评论。

// Call getMenu() to ensure the menu is created, and so, also are the filters. We cannot call
// createFilters() withouth having a menu because it will cause in a recursion to applyState()
// that ends up to clear all the filter values. This is likely to happen when we reorder a column
// and then add a new filter before the menu is recreated.
me.view.headerCt.getMenu();

您可以在应用过滤器之前测试是否已创建菜单。如果没有,请自己动手。

if(!grid.getView().headerCt.menu){
    grid.getView().headerCt.getMenu();
}