Hi I am trying to work with the store filterBy function but i am unable to make it work as I want. I have four buttons(A B C D) and a list with all data related to buttons When I click on the button I should filter accordingly Note:- when I click A ,I should get records of A when I click B , I should get records of B appended to A's list of records So actually when I click on the buttons I should have a array of button ids and filter the the list using these id's.
filterList:function (list, index, target, record){
var categories=[];
categories.push(record.get('id'));
for(c=0;c<categories.length;c++)
{
Ext.getStore('mystore').filterBy(function(record){
var id = record.get('id');
if(id==categories[c])
{
return true;
}
});
}
}
Any help is appreciated.
The filterBy
return function should always return a boolean value
. You are only returning true
, and no false
. Besides that you are filtering
the store
in a loop
, and the parameter record
exists twice (as a parameter in the function filterList and in the return function of the filterBy).
I created a Fiddle to show you where I came up with. I know it is ExtJs
instead of Sencha Touch
, but you will get the idea. I will step through the MainController
, where all the logic is.
I didn't clean the code so there is some duplication, but it's just a concept.
First I create a set of buttons on my view
. See that I'm setting an action property
.
...
tbar: [{
text: 'Filter a',
action: 'a'
}, {
text: 'Filter b',
action: 'b'
}],
...
Then I bind an onClick
event to the button. In this event I use the action property as a searchValue, but it could be anything of course.
...
onClick: function(button, event, eOpts) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
filters = store.getFilters(),
searchValue = button.action,
regex = RegExp(searchValue, 'i'),
filter = new Ext.util.Filter({
id: button.id,
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
});
if (filters.containsKey(button.id)) {
store.removeFilter(filter);
} else {
store.addFilter(filter);
}
},
...
The magic is in the filter instance
. By adding new filter instances
each time you filter, you can filter with several filters. If you push button a
and button b
they will respect each other. In that filter I use a regex
to search through all data
of the current model
. I config an id
to recognize the filter so I can remove it afterwards.
filter = new Ext.util.Filter({
id: button.id,
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
});
If the filter doesn't exists it will be added, otherwise it will be removed.
if (filters.containsKey(button.id)) {
store.removeFilter(filter);
} else {
store.addFilter(filter);
}
I also created a textfield
to search through all data. Instead of adding and removing filters
I just call clearFilter
and add a new filter
with new searchvalue
.
onKeyUp: function(textField, event, eOpts) {
this.filterStore(textField.getValue());
},
filterStore: function(searchValue) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
regex = RegExp(searchValue, 'i');
store.clearFilter(true);
store.filter(new Ext.util.Filter({
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
}));
}
Ext.define('Filtering.controller.MainController', {
extend: 'Ext.app.Controller',
config: {
refs: {
mainGrid: 'maingrid'
}
},
init: function() {
var me = this;
me.listen({
global: {},
controller: {},
component: {
'segmentedbutton': {
toggle: 'onToggle'
},
'toolbar > button': {
click: 'onClick'
},
'textfield': {
keyup: 'onKeyUp'
}
},
store: {
'*': {
metachange: 'onMetaChange',
filterchange: 'onFilterChange'
}
},
direct: {}
});
},
onLaunch: function() {
var store = Ext.StoreManager.lookup('Users') || Ext.getStore('Users');
store.load();
},
onMetaChange: function(store, metaData) {
var grid = this.getMainGrid(),
model = store.getModel(),
// metadata
fields = metaData.fields,
columns = metaData.columns,
gridTitle = metaData.gridTitle;
model.fields = fields;
grid.setTitle(gridTitle);
grid.reconfigure(store, columns);
},
onFilterChange: function(store, filters, eOpts) {
var me = this,
grid = me.getMainGrid();
grid.getSelectionModel().select(0);
},
/**
* Used for the segmented buttons
*/
onToggle: function(container, button, pressed) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
//filters = store.getFilters(),
searchValue = button.action,
regex = RegExp(searchValue, 'i'),
filter = new Ext.util.Filter({
id: button.id,
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
});
if (pressed) {
store.addFilter(filter);
} else {
store.removeFilter(filter);
}
},
/**
* Used for the toolbar buttons
*/
onClick: function(button, event, eOpts) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
filters = store.getFilters(),
searchValue = button.action,
regex = RegExp(searchValue, 'i'),
filter = new Ext.util.Filter({
id: button.id,
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
});
if (filters.containsKey(button.id)) {
store.removeFilter(filter);
} else {
store.addFilter(filter);
}
},
/**
* Used for the textfield
*/
onKeyUp: function(textField, event, eOpts) {
this.filterStore(textField.getValue());
},
filterStore: function(searchValue) {
var me = this,
grid = me.getMainGrid(),
store = grid.getStore(),
regex = RegExp(searchValue, 'i');
store.clearFilter(true);
store.filter(new Ext.util.Filter({
filterFn: function(record) {
var match = false;
Ext.Object.each(record.data, function(property, value) {
match = match || regex.test(String(value));
});
return match;
}
}));
}
});
Ext.define('Filtering.view.MainGrid', {
extend: 'Ext.grid.Panel',
xtype: 'maingrid',
tbar: [{
xtype: 'segmentedbutton',
allowMultiple: true,
items: [{
text: 'Filter a',
action: 'a'
}, {
text: 'Filter b',
action: 'b'
}]
}, {
text: 'Filter a',
action: 'a'
}, {
text: 'Filter b',
action: 'b'
}, {
xtype: 'textfield',
emptyText: 'Search',
enableKeyEvents: true
}],
//title: 'Users', // Title is set through the metadata
//store: 'Users', // we reconfigure the store in the metachange event of the store
columns: [] // columns are set through the metadata of the store (but we must set an empty array to avoid problems)
});