【问题标题】:Sencha Touch store filterBy functionSencha Touch商店过滤功能
【发布时间】:2015-12-28 01:47:43
【问题描述】:

您好,我正在尝试使用 store filterBy 功能,但无法使其按我的意愿工作。 我有四个按钮(A B C D)和一个包含与按钮相关的所有数据的列表 当我点击按钮时,我应该相应地过滤 注意:- 当我点击 A 时,我应该得到 A 的记录 当我点击 B 时,我应该将 B 的记录附加到 A 的记录列表中 所以实际上当我点击按钮时,我应该有一个按钮 id 数组并使用这些 id 过滤列表。

  filterList:function (list, index, target, record){
    var categories=[];
    categories.push(record.get('id'));
                                for(c=0;c<categories.length;c++)
                                {
                                Ext.getStore('mystore').filterBy(function(record){
                                  var id = record.get('id');
                                       if(id==categories[c])
                                        {       
                                            return true; 
                                        }

                                });
                                }

    }

感谢任何帮助。

【问题讨论】:

  • 您的问题让我感到困惑,您是否在单击按钮时过滤或附加数组有问题?
  • @SagarKhatri,我的过滤有问题,假设将按钮视为开关,当我打开按钮 A 和 B 时,我的列表应该过滤 A 和 B 的值

标签: javascript extjs sencha-touch sencha-touch-2 store


【解决方案1】:

你的代码有什么问题

filterBy 返回函数应该总是返回boolean value。你只返回true,没有false。除此之外,您是loop 中的storestore,并且参数record 存在两次作为函数filterList 中的参数 在filterBy的返回函数中)。

示例

我创建了一个Fiddle 来向您展示我的想法。我知道是ExtJs 而不是Sencha Touch,但你会明白的。我将逐步介绍所有逻辑所在的MainController

我没有清理代码,所以有一些重复,但这只是一个概念。

设置一些逻辑

首先,我在view 上创建了一组按钮。看到我设置了action property

...
tbar: [{
    text: 'Filter a',
    action: 'a'
}, {
    text: 'Filter b',
    action: 'b'
}],
...

然后我将onClick 事件绑定到按钮。在这种情况下,我将 action 属性用作 searchValue,但它当然可以是任何东西。

...
onClick: function(button, event, eOpts) {
    var me = this,
        grid = me.getMainGrid(),
        store = grid.getStore(),
        filters = store.getFilters(),
        searchValue = button.action,
        regex = RegExp(searchValue, 'i'),
        filter = new Ext.util.Filter({
            id: button.id,
            filterFn: function(record) {
                var match = false;
                Ext.Object.each(record.data, function(property, value) {
                    match = match || regex.test(String(value));
                });
                return match;
            }
        });

    if (filters.containsKey(button.id)) {
        store.removeFilter(filter);
    } else {
        store.addFilter(filter);
    }
},
...

魔法

神奇之处在于filter instance。通过在每次过滤时添加new filter instances,您可以使用多个过滤器进行过滤。如果你推button abutton b 他们会互相尊重。在该过滤器中,我使用regex 搜索当前model 的所有data。我配置了一个id 来识别过滤器,以便之后可以将其删除。

filter = new Ext.util.Filter({
    id: button.id,
    filterFn: function(record) {
        var match = false;
        Ext.Object.each(record.data, function(property, value) {
            match = match || regex.test(String(value));
        });
        return match;
    }
});

如果过滤器不存在,则添加,否则删除。

if (filters.containsKey(button.id)) {
    store.removeFilter(filter);
} else {
    store.addFilter(filter);
}

重置过滤器

我还创建了一个textfield 来搜索所有数据。我没有添加和删除filters,而是调用clearFilter并添加一个新的filter和新的searchvalue

onKeyUp: function(textField, event, eOpts) {
    this.filterStore(textField.getValue());
},

filterStore: function(searchValue) {
    var me = this,
        grid = me.getMainGrid(),
        store = grid.getStore(),
        regex = RegExp(searchValue, 'i');

    store.clearFilter(true);

    store.filter(new Ext.util.Filter({
        filterFn: function(record) {
            var match = false;
            Ext.Object.each(record.data, function(property, value) {
                match = match || regex.test(String(value));
            });
            return match;
        }
    }));
}

完整的主控制器

Ext.define('Filtering.controller.MainController', {
    extend: 'Ext.app.Controller',

    config: {
        refs: {
            mainGrid: 'maingrid'
        }
    },

    init: function() {
        var me = this;

        me.listen({
            global: {},
            controller: {},
            component: {
                'segmentedbutton': {
                    toggle: 'onToggle'
                },
                'toolbar > button': {
                    click: 'onClick'
                },
                'textfield': {
                    keyup: 'onKeyUp'
                }
            },
            store: {
                '*': {
                    metachange: 'onMetaChange',
                    filterchange: 'onFilterChange'
                }
            },
            direct: {}
        });
    },

    onLaunch: function() {
        var store = Ext.StoreManager.lookup('Users') || Ext.getStore('Users');

        store.load();
    },

    onMetaChange: function(store, metaData) {
        var grid = this.getMainGrid(),
            model = store.getModel(),
            // metadata
            fields = metaData.fields,
            columns = metaData.columns,
            gridTitle = metaData.gridTitle;

        model.fields = fields;
        grid.setTitle(gridTitle);
        grid.reconfigure(store, columns);
    },

    onFilterChange: function(store, filters, eOpts) {
        var me = this,
            grid = me.getMainGrid();

        grid.getSelectionModel().select(0);
    },

    /**
     * Used for the segmented buttons
     */
    onToggle: function(container, button, pressed) {
        var me = this,
            grid = me.getMainGrid(),
            store = grid.getStore(),
            //filters = store.getFilters(),
            searchValue = button.action,
            regex = RegExp(searchValue, 'i'),
            filter = new Ext.util.Filter({
                id: button.id,
                filterFn: function(record) {
                    var match = false;
                    Ext.Object.each(record.data, function(property, value) {
                        match = match || regex.test(String(value));
                    });
                    return match;
                }
            });

        if (pressed) {
            store.addFilter(filter);
        } else {
            store.removeFilter(filter);
        }
    },

    /**
     * Used for the toolbar buttons
     */
    onClick: function(button, event, eOpts) {
        var me = this,
            grid = me.getMainGrid(),
            store = grid.getStore(),
            filters = store.getFilters(),
            searchValue = button.action,
            regex = RegExp(searchValue, 'i'),
            filter = new Ext.util.Filter({
                id: button.id,
                filterFn: function(record) {
                    var match = false;
                    Ext.Object.each(record.data, function(property, value) {
                        match = match || regex.test(String(value));
                    });
                    return match;
                }
            });

        if (filters.containsKey(button.id)) {
            store.removeFilter(filter);
        } else {
            store.addFilter(filter);
        }
    },

    /**
     * Used for the textfield
     */
    onKeyUp: function(textField, event, eOpts) {
        this.filterStore(textField.getValue());
    },

    filterStore: function(searchValue) {
        var me = this,
            grid = me.getMainGrid(),
            store = grid.getStore(),
            regex = RegExp(searchValue, 'i');

        store.clearFilter(true);

        store.filter(new Ext.util.Filter({
            filterFn: function(record) {
                var match = false;
                Ext.Object.each(record.data, function(property, value) {
                    match = match || regex.test(String(value));
                });
                return match;
            }
        }));
    }
});

完整视图

Ext.define('Filtering.view.MainGrid', {
    extend: 'Ext.grid.Panel',
    xtype: 'maingrid',

    tbar: [{
        xtype: 'segmentedbutton',
        allowMultiple: true,
        items: [{
            text: 'Filter a',
            action: 'a'
        }, {
            text: 'Filter b',
            action: 'b'
        }]
    }, {
        text: 'Filter a',
        action: 'a'
    }, {
        text: 'Filter b',
        action: 'b'
    }, {
        xtype: 'textfield',
        emptyText: 'Search',
        enableKeyEvents: true
    }],
    //title: 'Users', // Title is set through the metadata
    //store: 'Users', // we reconfigure the store in the metachange event of the store
    columns: [] // columns are set through the metadata of the store (but we must set an empty array to avoid problems)
});

【讨论】:

    【解决方案2】:

    假设您有两个切换按钮,并且您希望在切换这些按钮时过滤存储,

    控制器

     Ext.define('namespace',{
        extend:'controller...',
        config:{
           refs:{
               btnA:'#btnA',
               btnB:'#btnB',
           },
           controls:{
              btnA:{
                 change:'btnChange'
              },
              btnB:{
                 change:'btnChange'
              }
          }
        },
        btnChange:function(ths,val){
           var btnA = this.getBtnA().getValue(),
               btnB = this.getBtnB().getValue();
    
           Ext.getStore('mystore').filterBy(function(r){
               if(btnA && btnB){
                   return r.get('id') === btnA.getValue() || r.get('id') === btnB.getValue();
               }else if(btnA){
                  return r.get('id') === btnA.getValue();
               }else if(btnB){
                  return r.get('id') === btnB.getValue();
               }
    
               return false;
           });
        }
     });
    

    【讨论】: