title: How to apply filter function to paging grid with local(memory) store in ExtJS6?
body: <p>I have a paging grid with local store, and I want to apply a filter using my own function. But it is failed.</p>
  
  <p>From internet recommendations I used <code>remoteFilter: true</code> and <code>enablePaging: true</code> options in store config.</p>
  
  <p>And it works perfectly if I filter store with specific configuration object:</p>
  
  <pre><code>store.filter([{ property: 'age', value: 12 }]);
  </code></pre>
  
  <p>unfortunately it is not enough to build complex filter criteria.</p>
  
  <p>In accordance with <a href="https://docs.sencha.com/extjs/6.6.0/classic/Ext.data.Store.html#method-filterBy" rel="nofollow noreferrer">documentation</a> there is a special <code>filterBy</code> method in store object to use function as filter. But, when I am providing it like this:</p>
  
  <pre><code>store.filterBy( function( record ) {
    return record.get( 'age' ) &lt;= 12;
  });
  </code></pre>
  
  <p>I got an error <code>Uncaught Error: Unable to use a filtering function in conjunction with remote filtering.</code></p>
  
  <p>Here is my working example in fiddle <a href="https://fiddle.sencha.com/#fiddle/2u8l" rel="nofollow noreferrer">https://fiddle.sencha.com/#fiddle/2u8l</a></p>
  
  <p>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</p>
  
  <pre><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 ) &lt;= 12;
      },
  
      toggleFilter: function( fltr ) {
          var store = this.getViewModel().getStore( 'simpsons' );
          var filters = store.getFilters();
          if ( filters.length &gt; 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"
              }]
          }
      }
  });
  
  
  
  </code></pre>
  
  <p>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:</p>
  
  <pre><code>name.lenght &lt;= 4 &amp;&amp;  ((year % 4 == 0) &amp;&amp; (year % 100 != 0)) || (year % 400 == 0)
  </code></pre>
  
  <p>Thank you in advance,
  A.</p>