ExtJS Store动态过滤已过滤的商店

时间:2013-07-25 00:13:29

标签: javascript extjs filter store

我正在创建一个与商店绑定的SearchAsYouType组合框。 它将输入标记为单词并将其(现在)与对象的所有属性进行匹配:

{"id": "id_someid",
 "lastName": "Porker",
 "firstName": "Peter"}

当组合框的输入发生变化时,我决定动态创建过滤器:

Ext.define('MyApp.controller.SearchFilterController', {
  extend: 'Ext.app.Controller',

   views: [
    'SearchAsYouTypeCombo'
   ],

   configureFiltersBeforeQuery: function(queryPlan) {
    //add filter per word token

    comboBox = queryPlan.combo;
    queryString = queryPlan.query;
    words = queryString.split(/[,\s]+/);
    myStore = comboBox.getStore(); 

    myStore.clearFilter(false); //I also tried without this line, did not help

    if(!Ext.isEmpty(queryString))
    {
        //create a filter per word
        filters = [];
        Ext.Array.each(words,
           function(word, index, wordsArray){ 
             console.log('NEW FILTER: word: ' + word);
             filterAllPropertiesFilter = 
                Ext.create('Ext.util.Filter',
                   { filterFn: function(item){
                        match = false;
                        Ext.Object.each(item.data,
                        function (property, value){
                        //match beginning of word
                        match = match || (String(value).toLowerCase().lastIndexOf(word.toLowerCase(), 0) === 0);
                    return !match; //do not check other properties when match is found
                });
                return match;
            }});
            filters.push(filterAllPropertiesFilter);
            return true;
        },
        this,
        false);
        myStore.addFilter(filters);
    }
    return true;
},

init: function(application) {
    this.control({
        'SearchAsYouTypeCombo': {
            beforequery: this.configureFiltersBeforeQuery
        }
    });
}

});

编辑:我的商店里有一个“凯文培根”。 假设本地商店中其他人的LastNames都没有以“Ba”开头,但还有其他人的firstName是“Barry”。因此,当我输入搜索查询“Ba”时,我希望将“Kevin Bacon”和“Barry White”视为结果。这很有效。

但这是我无法完成的事情:  当我现在继续将searchString扩展为“Ba,Ke”时,我不希望代码在应用过滤器时再次对我商店中的所有人进行交互。我希望即将推出的过滤器只检查前一个过滤器的左侧两个结果。 我有点想在另一个过滤器上应用过滤器。

1 个答案:

答案 0 :(得分:2)

您将无法使用商店的过滤器完成所需的操作,因为这些方法最终都会对整个数据集进行过滤。因此,您需要自己应用过滤器!

为了做到这一点,我们需要复制Ext.data.Store#filter中的代码,除了在过滤之前恢复整个数据集的部分。

这给了我们:

// -- Ensure that our current filter is not stalled ----------------

// Clear our filtering if the query string has changed in a way
// that invalidate the current filtering
if (
    // previous filter is stalled
) {
    myStore.data = myStore.snapshot;
    delete myStore.snapshot;
}

// -- Create your new or updated filter ----------------------------

var filter = new Ext.util.Filter({
    filterFn: function(record) {
        // your filtering logic
    }
});

// -- Apply the filter to the currently filtered data --------------

myStore.snapshot = myStore.snapshot || myStore.data.clone();

// !!!
// Here's the essential difference. We filter from the filtered dataset:
myStore.data = myStore.data.filter(myFilter);

// Instead of starting again from the unfiltered snapshot like in the original code:
//me.data = me.snapshot.filter(filters);

myStore.constructGroups();

if (myStore.sorters.length && myStore.sortOnFilter && !myStore.remoteSort) {
    myStore.sort();
} else {
    // fire datachanged event if it hasn't already been fired by doSort
    myStore.fireEvent('datachanged', myStore);
    myStore.fireEvent('refresh', myStore);
}

// This line's probably useless since filters haven't actually changed...
//myStore.fireEvent('filterchange', myStore, myStore.filters.items);

正如我在之前的评论中暗示的那样,您显然需要一种方法来检测查询字符串何时发生更改,从而使当前过滤过时。我在代码的开头添加了一个模拟条件,向您展示如何在发生这种情况时清除这个hacky过滤。