简体   繁体   中英

Sencha Touch store filterBy function

Hi I am trying to work with the store filterBy function but i am unable to make it work as I want. I have four buttons(ABCD) and a list with all data related to buttons When I click on the button I should filter accordingly Note:- when I click A ,I should get records of A when I click B , I should get records of B appended to A's list of records So actually when I click on the buttons I should have a array of button ids and filter the the list using these id's.

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

                                });
                                }

    }

Any help is appreciated.

What is wrong with your code

The filterBy return function should always return a boolean value . You are only returning true , and no false . Besides that you are filtering the store in a loop , and the parameter record exists twice ( as a parameter in the function filterList and in the return function of the filterBy ).

Example

I created a Fiddle to show you where I came up with. I know it is ExtJs instead of Sencha Touch , but you will get the idea. I will step through the MainController , where all the logic is.

I didn't clean the code so there is some duplication, but it's just a concept.

Setting up some logic

First I create a set of buttons on my view . See that I'm setting an action property .

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

Then I bind an onClick event to the button. In this event I use the action property as a searchValue, but it could be anything of course.

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

The magic

The magic is in the filter instance . By adding new filter instances each time you filter, you can filter with several filters. If you push button a and button b they will respect each other. In that filter I use a regex to search through all data of the current model . I config an id to recognize the filter so I can remove it afterwards.

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 the filter doesn't exists it will be added, otherwise it will be removed.

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

Reset filters

I also created a textfield to search through all data. Instead of adding and removing filters I just call clearFilter and add a new filter with new 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;
        }
    }));
}

The complete maincontroller

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

The complete view

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

Assuming you have two toggle buttons and you want to filter store on toggling of those buttons,

Controller

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM