How to apply filter function to paging grid with local(memory) store in ExtJS6?

佐手、 提交于 2021-01-29 11:23:48

问题


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:

  1. Configure store with remoteFilter: true and enablePaging: true options:
{
 model: 'Ext.data.Model',
 pageSize: 2,
 remoteFilter: true,
 proxy: {
   type: 'memory',
   enablePaging: true,
   reader: {
     type: 'json'
   }
 }
}
  1. Load data into the store using its Proxy instead of loadData method:
store.getProxy().data = this.getSimpsonsData().items;
store.reload();
  1. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!