4

I am creating a SearchAsYouType Combobox tied to a Store. It features tokenizing the input into words and match it (for now) against all properties of an Object:

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

I decided to create the Filters on the fly when the input of the combobox changes:

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

});

EDIT: There is a "Kevin Bacon" in my Store. Let's say that none of the LastNames of the other Persons in the local Store starts with "Ba", but there is someone else whose firstName is "Barry". So when I type in the search query "Ba" I want to see "Kevin Bacon" and "Barry White" as results. This works.

But here is what I cannot accomplish: When I now go on extending the searchString to "Ba, Ke" I don't want the code to interate over all Persons in my Store again when applying the filter. I want the upcoming filter to only check against the left two results from the previous filter. I kinda want to apply a filter upon another filter.

4

1 回答 1

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 过滤。

于 2013-07-25T01:05:02.767 回答