我正在创建一个与商店绑定的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”时,我不希望代码在应用过滤器时再次对我商店中的所有人进行交互。我希望即将推出的过滤器只检查前一个过滤器的左侧两个结果。 我有点想在另一个过滤器上应用过滤器。
答案 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过滤。