如何在ExtJS6中使用本地(内存)存储将过滤功能应用于分页网格?

问题描述 投票:0回答:2

我有一个带有本地存储的分页网格,我想使用我自己的函数应用过滤器。但失败了。

根据互联网的建议,我在商店配置中使用了

remoteFilter: true
enablePaging: true
选项。

如果我使用特定的配置对象过滤存储,它会完美地工作:

store.filter([{ property: 'age', value: 12 }]);

不幸的是,建立复杂的过滤标准还不够。

根据文档,存储对象中有一个特殊的

filterBy
方法可以使用函数作为过滤器。但是,当我这样提供时:

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/#fiddle/2u8l

这是我的商店配置和控制器的所有业务逻辑。我将在这里跳过视图配置,重点关注代码的主要部分(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": "[email protected]",
                "phone": "555-111-1224"
            }, {
                'name': 'Bart',
                'age': 8,
                "email": "[email protected]",
                "phone": "555-222-1234"
            }, {
                'name': 'Homer',
                'age': 40,
                "email": "[email protected]",
                "phone": "555-222-1244"
            }, {
                'name': 'Marge',
                'age': 34,
                "email": "[email protected]",
                "phone": "555-222-1254"
            }]
        }
    }
});



一般来说,我希望能够以编程方式使用本地存储在分页网格上设置过滤条件。函数允许我扩展过滤功能并使用连接和讨论构建灵活的逻辑表达式。例如:

name.lenght <= 4 &&  ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)

预先感谢您, A.

filter extjs pagination grid local
2个回答
1
投票

您不能在一家商店同时使用

remoteFilter
filterBy
。决定过滤器的逻辑应该在哪里 - 在
Client Side
Server Side

如果打开

server side
,请将
remoteFilter
设置为
true
并使用带有额外参数的
filter
操作,您可以在服务器上捕获这些参数并执行过滤器。

如果打开

client side
,请将
remoteFilter
设置为
false
并使用
filterBy
功能,如您所附。

检查小提琴上的示例(我刚刚更改了一些内容):https://fiddle.sencha.com/#fiddle/2ua4&view/editor


0
投票

我终于解决了这个问题!

在下一行中提及的 store 的 onFilterEndUpdate 方法中引发的错误:

...
me.getFilters().each(function(filter) {
  if (filter.getInitialConfig().filterFn) {
    Ext.raise('Unable to use a filtering function in conjunction with remote filtering.');
  }
});
...

我已经在我的商店实体中重写了此方法并注释掉了这些行。 我知道这不是最好的解决方案,但我找不到更好的解决方案。

这是有关此主题的完整解决方案:

  1. 使用
    remoteFilter: true
    enablePaging: true
    选项配置商店:
{
 model: 'Ext.data.Model',
 pageSize: 2,
 remoteFilter: true,
 proxy: {
   type: 'memory',
   enablePaging: true,
   reader: {
     type: 'json'
   }
 }
}
  1. 使用其
    Proxy
    而不是
    loadData
    方法将数据加载到存储中:
store.getProxy().data = this.getSimpsonsData().items;
store.reload();
  1. 存储初始化后重写 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/#fiddle/2ub7

© www.soinside.com 2019 - 2024. All rights reserved.