问题
I have a paging grid with local store, and I want to apply a filter using my own function. But it is failed.
From internet recommendations I used remoteFilter: true
and enablePaging: true
options in store config.
And it works perfectly if I filter store with specific configuration object:
store.filter([{ property: 'age', value: 12 }]);
unfortunately it is not enough to build complex filter criteria.
In accordance with documentation there is a special filterBy
method in store object to use function as filter. But, when I am providing it like this:
store.filterBy( function( record ) {
return record.get( 'age' ) <= 12;
});
I got an error Uncaught Error: Unable to use a filtering function in conjunction with remote filtering.
Here is my working example in fiddle https://fiddle.sencha.com/#fiddle/2u8l
This is my store configuration and all business logic from controller. I'll skip view configuration here to focus on main part( IMO )of code
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"
}]
}
}
});
In general I want to have ability to set up filter criteria on paging grid with local store programmatically. Function allows me to extend filter capabilities and build flexible logical expression using conjunction and disquisition. For example:
name.lenght <= 4 && ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)
Thank you in advance, A.
回答1:
You can't use both remoteFilter
and filterBy
in one store. Decide where should be the logic of the filter - on Client Side
or Server Side
?
If on server side
, set the remoteFilter
as true
and use filter
action with extra paramaters which you can catch on server and perform the filter.
If on client side
, set the remoteFilter
as false
and use filterBy
function like you attached.
Check the example on fiddle (I just changed a few things): https://fiddle.sencha.com/#fiddle/2ua4&view/editor
回答2:
I have finally resolved this issue!
Mentioned error raised in onFilterEndUpdate method of store in next lines:
...
me.getFilters().each(function(filter) {
if (filter.getInitialConfig().filterFn) {
Ext.raise('Unable to use a filtering function in conjunction with remote filtering.');
}
});
...
I have override this method in my store entity and commented out these lines. I know it is not best solution, but I could not find better one.
Here is the complete solution concerning this topic:
- Configure store with
remoteFilter: true
andenablePaging: true
options:
{
model: 'Ext.data.Model',
pageSize: 2,
remoteFilter: true,
proxy: {
type: 'memory',
enablePaging: true,
reader: {
type: 'json'
}
}
}
- Load data into the store using its
Proxy
instead ofloadData
method:
store.getProxy().data = this.getSimpsonsData().items;
store.reload();
- Override method onFilterEndUpdate after store initialization and comment out mentioned lines i.e:
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());
}
Here is live example in fiddle https://fiddle.sencha.com/#fiddle/2ub7
来源:https://stackoverflow.com/questions/57277812/how-to-apply-filter-function-to-paging-grid-with-localmemory-store-in-extjs6