3

I have a store configured with memory proxy with enablePaging: true. Store's remoteFilter and remoteSort set to true so filtering and sorting requests handled by proxy.

When I filter my store by multiple fields I want to use OR condition, not AND.

Without memory proxy paging I could use remoteFilter: false and custom filter function like:

store.filterBy(function (record)
{
    for (var i = 0; i < searchFields.length; ++i) {
        if (record.get(searchFields[i]).toLowerCase().indexOf(searchText) !== -1) {
            return true;
        }
    }
    return false;
});

But how I can achieve this with enabled paging? Override memory proxy?

Sergey Novikov
  • 4,096
  • 7
  • 33
  • 59

2 Answers2

3

Ext.data.proxy.Memory.read use Ext.util.Filter.createFilterFn to create a filter function based on passed Ext.util.Filter[] (with property-value configs):

// Filter the resulting array of records 
if (filters && filters.length) {
    // Total will be updated by setting records 
    resultSet.setRecords(records = Ext.Array.filter(records, Ext.util.Filter.createFilterFn(filters)));
    resultSet.setTotal(records.length);
}

So, if you want to use different filter logic, you can override memroy proxy read method and use custom function to create filter function:

Ext.define('MyApp.extensions.FilterMemoryProxy', {
    extend: 'Ext.data.proxy.Memory',
    alias: 'proxy.filtermemory',

    createCustomFilterFn: function (filters)
    {
        if (!filters) {
            return Ext.returnTrue;
        }
        return function (candidate)
        {
            var items = filters.isCollection ? filters.items : filters,
                length = items.length,
                i, filter;
            for (i = 0; i < length; i++) {
                filter = items[i];
                if (!filter.getDisabled() && candidate.get(filter.getProperty()).toLowerCase().indexOf(
                        filter.getValue().toLowerCase()) !== -1) {
                    return true;
                }
            }
            return false;
        };
    },

    read: function (operation)
    {

        ...

        if (operation.process(resultSet, null, null, false) !== false) {
            // Filter the resulting array of records
            if (filters && filters.length) {
                // Total will be updated by setting records
                resultSet.setRecords(records = Ext.Array.filter(records, me.createCustomFilterFn(filters)));
                resultSet.setTotal(records.length);
            }

        ...

        }
    }
});
Sergey Novikov
  • 4,096
  • 7
  • 33
  • 59
1

You can override the memory proxy to suit your needs, or, if you only wish to find a string in one of the fields specified in searchFields, you can add a 'virtual' field to the model with the convert method specified.

For example:

// Extend Ext.data.Model or create it. Dealer's choice.
Ext.define('MyLocalModel', {
    extend: 'Ext.data.model',
    fields: [
        ...
        {
            name: 'searchField',
            type: 'string',
            convert: function(value, record) {
                // Get search fields somewhere
                var resultArray = [];
                for (var i = 0; i < searchFields.length; ++i) {
                    var searchField = searchFields[i];
                    var fieldValue = record.get(searchField);
                    resultArray.push(fieldValue);
                }

                // Join by a string that would not normally be searched
                // so that field values 'foo' and 'bar' are not valid when searching 'ooba'
                var result = resultArray.join('**');
                return result;
            }
        }
    ]
});

All you need to do in the store then is:

store.filter('searchField', searchText);

It's not exactly what you are searching for, but it should get the job done.

MarthyM
  • 1,839
  • 2
  • 21
  • 23
  • Thanks for idea, but I have a lot of data and I think that ~doubling it can affect performance (maybe Im wrong, Ill check), so Ill try to find a different solution. Looks like I have no other option but override proxy and use the second store. – Sergey Novikov Jul 04 '17 at 17:53
  • Yes, it is not ideal. For larger portions of data I would recommend creating a custom proxy. – MarthyM Jul 04 '17 at 18:04