I had to do this also. It was part of a bigger function that applied a JSON "grid format object" (containing any number of grid filters, visible columns and a sort column and direction) to a rendered grid panel.
The requirement was that a user needed to be able save the existing gridpanel's visible columns, applied filters and applied sorting into a database with a name and then at later date be able to re-apply these three things to a grid panel to get the same filters, visible columns and sort state by selecting their saved format.
I also did not want to use the store filter because the selected filter options needed to be visible on the gridpanel filter feature UI (the grid filter drop menus) in case the user wanted to adjust them.
Here's an example of a grid format JSON that would be saved by a user:
{
"columns":[
"first_name",
"last_name",
"course",
"course_room",
"student_status",
"start_date",
"schedule",
"time_on_course",
"attendance",
"this_period",
"acct_bal"
],
"filters":[{
"field":"student_status",
"data":{
"type":"list",
"value":"Attending"
}
}],
"sort":{
"property":"start_date",
"direction":"ASC"
}
}
Here is the function, the JSON is used as the argument:
applyLogFormat: function(format) {
var log = this.getLog(),
format = Ext.JSON.decode(format);
log.filters.autoReload = false;
// apply the grid filters correctly
log.filters.clearFilters();
Ext.each(format.filters, function(filter) {
var gridFilter = log.filters.getFilter(filter.field);
gridFilter.setActive(true);
switch(gridFilter.type) {
case 'date':
var dateValue = Ext.Date.parse(filter.data.value, 'm/d/Y'),
value = filter.data.comparison == 'gt' ? {after: dateValue} : {before: dateValue};
gridFilter = log.filters.getFilter(filter.field);
gridFilter.setValue(value);
break;
case 'list':
gridFilter = log.filters.getFilter(filter.field);
gridFilter.menu.setSelected(gridFilter.menu.selected, false);
gridFilter.menu.setSelected(filter.data.value.split(','), true);
break;
default :
gridFilter = log.filters.getFilter(filter.field);
gridFilter.setValue(filter.data.value);
break;
}
});
// remove any pre-existing sorting from the grid
Ext.each(log.columns, function(column, index) {
if (column.hasCls('x-column-header-sort-ASC') ||
column.hasCls('x-column-header-sort-DESC')) {
log.columns[index].setSortState(null);
return false;
}
});
// show only the specified columns
log.suspendLayout = true;
Ext.each(log.columns, function(column) {
if (column.dataIndex) {
column.setVisible(Ext.Array.contains(format.columns, column.dataIndex));
}
});
log.suspendLayout = false;
log.doComponentLayout();
// set the sorter
if (format.sort) {
var column = log.down('gridcolumn[dataIndex=' +
format.sort.property + ']');
column.setSortState(format.sort.direction);
log.filters.autoReload = true;
} else {
log.store.sorters.clear();
log.store.loadPage(1);
log.filters.autoReload = true;
}
}
This was all done for 4.1.0
EDIT:
I realized there was an important part of the implementation which isn't visible from that function.
Normally the gridpanel filter feature
menus do not get created until a user physically clicks on one of them. Then they are all created. I suppose this is for memory saving purposes?
Obviously, this function will not work until the filter menus have been created.
To handle this I explicitly create them in the gridpanel's afterrender
event so that they are available right away. This function will then work even if a user has not clicked on one of the filter menus.
I am using the MVC pattern so I did from the gridpanel's controller, like this:
// code from gridpanel's controller
var me = this;
me.control({
'log': {
afterrender: function() {
me.getLog().filters.createFilters();
},
},
// ... other event handlers
});