Применить сеточный фильтр программно из функции - PullRequest
6 голосов
/ 09 марта 2012

Используя 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 ]

9 голосов
/ 09 марта 2012

У меня есть обходной путь:

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 раза.

6 голосов
/ 17 августа 2012

В качестве обновления я расширил эту функцию и изменил ее для работы с ExtJS 4.1.1

Вот пример функции для динамической установки сеточных фильтров (без необходимости нажимать пункты меню). После этого отфильтрованные элементы будут видны пользователю в меню заголовка столбца сетки, как если бы он щелкнул по ним и установил их вручную.

Аргумент "grid" - это сетка с 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;
        }
    });
}

Вот пример массива объектов «filter».

// 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 сеточные фильтры «создаются» при первом нажатии пользователем одного из них, что может не произойти, если пользователь просто хочет применить один из этих предопределенных фильтров.

Это можно легко сделать, включив этого слушателя последующего события в сетку.

listeners: {

    // must create the filters after grid is rendered
    afterrender: function(grid) {
        grid.filters.createFilters();
    }
}
3 голосов
/ 21 сентября 2012

Просто добавьте

filter: true

к описанию столбцов сетки, например:

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

, если вы хотите, чтобы фильтр работал после первой попытки, создайте первый экземпляр.

1 голос
/ 09 марта 2012

Вот кое-что, на что стоит обратить внимание. Похоже, что плагин фильтров прослушивает событие 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);
},
0 голосов
/ 23 июля 2013

В источнике вы можете увидеть комментарий, связанный с этим.

// 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();
}
0 голосов
/ 05 апреля 2012

Я нашел другой способ реализовать это. Похоже, что элементы сетки привязываются к сетке только после визуализации сетки. Это означает, что любая настройка фильтра не вступит в силу, пока не будет отображена сетка. Начальная загрузка хранилища, по-видимому, инициируется до визуализации сетки.

Я решил свою проблему, создав свой магазин с прокси памяти, не содержащим данных.

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();
},
0 голосов
/ 09 марта 2012

Хотите применить сеточный фильтр или может быть лучше подойдет функция store.filter ()? В этом случае просто отфильтруйте хранилище, и сетка отобразит отфильтрованные записи.

...