Как применить функцию фильтра к сетке подкачки с локальным (памятью) хранилищем в ExtJS6?
У меня есть пейджинговая сетка с локальным хранилищем, и я хочу применить фильтр, используя свою собственную функцию. Но это не удалось.
Из интернет-рекомендаций, которые я использовал remoteFilter: true
а также enablePaging: true
варианты в магазине конфиг.
И это прекрасно работает, если я фильтрую хранилище с конкретным объектом конфигурации:
store.filter([{ property: 'age', value: 12 }]);
к сожалению, этого недостаточно для построения сложных критериев фильтрации.
В соответствии с документацией filterBy
метод в объекте store для использования функции в качестве фильтра. Но когда я предоставляю это так:
store.filterBy( function( record ) {
return record.get( 'age' ) <= 12;
});
Я получил ошибку Uncaught Error: Unable to use a filtering function in conjunction with remote filtering.
Вот мой рабочий пример в скрипке https://fiddle.sencha.com/
Это конфигурация моего магазина и вся бизнес-логика от контроллера. Я пропущу просмотр конфигурации здесь, чтобы сосредоточиться на основной части ( IMO) кода
Ext.define('TestGridViewModelr', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myexmpl.main.testgrid',
data: {
},
formulas: {},
stores: {
simpsons: {
model: 'Ext.data.Model',// 'SimpsonModel',
pageSize: 2,
// remoteSort: true,
remoteFilter: true,
proxy: {
type: 'memory',
enablePaging: true,
reader: {
type: 'json',
rootProperty: 'items'
}
}
}
}
});
Ext.define('TestGridController', {
extend: 'Ext.app.ViewController',
alias: 'controller.myexmpl.main.testgrid',
init: function () {
console.log('controller inititalized\n init async store loading...');
setTimeout( this.onStoreLoad.bind( this ), 1000 );
},
initViewModel: function(vm){
console.log( 'viewModel init', vm.get('test') );
},
emptyMethod: function () {},
onStoreLoad: function () {
console.log('loading store');
var vm = this.getViewModel();
var store = vm.getStore('simpsons');
store.getProxy().data = this.getSimpsonsData().items;
store.reload();
// store.loadData( this.getSimpsonsData() );
},
//++++++++++++ FILTERING ++++++++
/* NO PROBLEM */
onToggleFilter: function () {
console.log('simple filter');
var filter = this.getSimpleFilter()
this.toggleFilter( filter );
},
/* PROBLEM */
onToggleFnFilter: function(){
console.log('function filter');
// var filterFn = this.filterChildren;
var filterFn = this.getFilterUtil()
this.toggleFilter( filterFn );
},
/* NO PROBLEM */
getSimpleFilter: function(){
return {
property: 'age',
value: '12'
};
},
/* PROBLEM */
getFilterUtil: function() {
return Ext.create( 'Ext.util.Filter', {
filterFn: this.filterChildren
})
},
filterChildren: function( record ) {
var age = record.get( 'age' );
console.log( 'filter record up to age:', age )// debugger;
return parseInt( age ) <= 12;
},
toggleFilter: function( fltr ) {
var store = this.getViewModel().getStore( 'simpsons' );
var filters = store.getFilters();
if ( filters.length > 0 ) {
store.clearFilter();
} else {
this. applyFilterToStore( fltr, store );
}
},
applyFilterToStore: function( filter, store ){
var method = Ext.isFunction( filter ) || filter instanceof Ext.util.Filter
? 'filterBy'
: 'setFilters';
store[method]( filter );
},
getSimpsonsData: function(){
return {
'items': [{
'name': 'Lisa',
'age': 12,
"email": "lisa@simpsons.com",
"phone": "555-111-1224"
}, {
'name': 'Bart',
'age': 8,
"email": "bart@simpsons.com",
"phone": "555-222-1234"
}, {
'name': 'Homer',
'age': 40,
"email": "homer@simpsons.com",
"phone": "555-222-1244"
}, {
'name': 'Marge',
'age': 34,
"email": "marge@simpsons.com",
"phone": "555-222-1254"
}]
}
}
});
В общем, я хочу, чтобы у меня была возможность настроить критерии фильтра для сетки подкачки с локальным хранилищем программно. Функция позволяет мне расширять возможности фильтра и создавать гибкое логическое выражение, используя соединение и разводку. Например:
name.lenght <= 4 && ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)
Заранее спасибо, А.
2 ответа
Я наконец решил эту проблему!
Упомянутая ошибка возникла в методе хранения onFilterEndUpdate в следующих строках:
...
me.getFilters().each(function(filter) {
if (filter.getInitialConfig().filterFn) {
Ext.raise('Unable to use a filtering function in conjunction with remote filtering.');
}
});
...
Я переопределил этот метод в моем объекте магазина и закомментировал эти строки. Я знаю, что это не лучшее решение, но я не смог найти лучшего.
Вот полное решение по этой теме:
- Настройте магазин с
remoteFilter: true
а такжеenablePaging: true
параметры:
{
model: 'Ext.data.Model',
pageSize: 2,
remoteFilter: true,
proxy: {
type: 'memory',
enablePaging: true,
reader: {
type: 'json'
}
}
}
- Загрузите данные в хранилище, используя его
Proxy
вместоloadData
метод:
store.getProxy().data = this.getSimpsonsData().items;
store.reload();
- Переопределите метод onFilterEndUpdate после инициализации хранилища и закомментируйте упомянутые строки, т.е.
onStoreLoad: function() {
...
store.onFilterEndUpdate = this.onFilterEndUpdate.bind( store );
...
},
onFilterEndUpdate: function() {
var me = this
, suppressNext = me.suppressNextFilter
, filters = me.getFilters(false);
// If the collection is not instantiated yet, it's because we are constructing.
if (!filters) {
return;
}
if (me.getRemoteFilter()) {
// me.getFilters().each(function(filter) {
// if (filter.getInitialConfig().filterFn) {
// Ext.raise('Unable to use a filtering function in conjunction with remote filtering.');
// }
// });
me.currentPage = 1;
if (!suppressNext) {
me.load();
}
} else if (!suppressNext) {
me.fireEvent('datachanged', me);
me.fireEvent('refresh', me);
}
if (me.trackStateChanges) {
// We just mutated the filter collection so let's save stateful filters from this point forward.
me.saveStatefulFilters = true;
}
// This is not affected by suppressEvent.
me.fireEvent('filterchange', me, me.getFilters().getRange());
}
Вот живой пример в скрипке https://fiddle.sencha.com/
Вы не можете использовать оба remoteFilter
а также filterBy
в одном магазине. Решите, где должна быть логика фильтра - вкл Client Side
или же Server Side
?
Если на server side
, установить remoteFilter
как true
и использовать filter
действие с дополнительными параметрами, которые вы можете поймать на сервере и выполнить фильтр.
Если на client side
, установить remoteFilter
как false
и использовать filterBy
Функция, как вы прилагается.
Проверьте пример на скрипке (я только что изменил несколько вещей): https://fiddle.sencha.com/#fiddle/2ua4&view/editor