Skip to content

Instantly share code, notes, and snippets.

@Eccenux
Last active August 22, 2016 11:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Eccenux/a112c72b9b88af359eea to your computer and use it in GitHub Desktop.
Save Eccenux/a112c72b9b88af359eea to your computer and use it in GitHub Desktop.
ExtJS Restore filters grid plugin
/* global Ext */
/**
* Restore filters grid plugin.
*
* To use this plugin just add to your grid
* 1. `'Ext.ux.grid.RestoreFilters'` in `requires` property
* 2. `ptype: 'gridrestorefilters'` in `plugins` property
* 3. and `restoreableFilters` array as a setting for the plugin (see below)
*
* Note! If you change `extraParams` after the grid was render (e.g. set extraParams state from URL hash)
* then you MUST use `extraParamsChanged` event
* @example Firering event after changing params:
* store.getProxy().extraParams = newParams;
* store.load();
* store.fireEvent('extraParamsChanged');
*
* Filters that can be restored:
* <li>simple filter (text)
* <li>xtype: 'combobox'
*
* Filters that CANNOT be restored:
* <li>type: 'combo' -- will probably fail because it expects a restricted set of values
* (might still work if you support it server side)
*
* @author Maciej "Nux" Jaros
* @license CC-BY
* https://gist.github.com/Eccenux/a112c72b9b88af359eea/
*
* Tested on ExtJS 6.0
*/
Ext.define('Ext.ux.grid.RestoreFilters', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.gridrestorefilters',
mixins: {
observable: 'Ext.util.Observable'
},
/**
* Extended grid object.
*/
grid : null,
/**
* array of dataIndexes of filters of which state can be restored
*/
restoreableFilters : null,
/**
* Plugin init.
* @param {Ext.grid.Panel} grid
*/
init: function(grid) {
var me = this;
//var config = this.getInitialConfig();
this.grid = grid;
// this is fine on first load
grid.on('beforeshow', function(){
console.log('RestoreFilters:grid.beforeshow');
me.restoreFiltersFromParms();
// this is for store.proxy.extraParams change (e.g. by hash change)
grid.store.on('extraParamsChanged', function() {
console.log('RestoreFilters:grid.store.extraParamsChanged');
me.restoreFiltersFromParms();
});
});
},
/**
* Restore filter state from extra params set in store's proxy.
*
* @note assumes `extraParams` are in form 'filter.dataIndex'
*
* @example the key of a column with `dataIndex:'status'` must be 'filter.status'.
*
* @warning Works for IE11+ (because of `element.dispatchEvent` and `Object.keys`)
*/
restoreFiltersFromParms: function() {
if (this.restoreableFilters === null) {
console.warn('restoreableFilters MUST be set in plugins object in the grid');
return;
}
// initial check
var grid = this.grid;
var store = grid.store;
if (!('extraParams' in store.proxy) || Object.keys(store.proxy.extraParams).length < 1) {
return;
}
// debug
console.log('extraParams: ', store.proxy.extraParams);
// set filters state
var filtersColumns = grid.filterBar.columns;
var filterdFields = grid.filterBar.fields;
var params = store.proxy.extraParams;
for (var i = 0; i < this.restoreableFilters.length; i++) {
var dataIndex = this.restoreableFilters[i];
var key = 'filter.' + dataIndex;
if (key in params) {
var value = params[key];
var index = filtersColumns.findIndex('dataIndex', dataIndex);
if (index >= 0) {
var el = filtersColumns.items[index].el.dom;
var input = el.querySelector('input');
// make sure to ignore values that are already set
if (input && input.value != value) {
filterdFields.items[index].setValue(value);
}
}
}
}
}
});
Ext.define('App.view.MyGrid', {
extend: 'Ext.grid.Panel',
requires: [
'Ext.ux.grid.RestoreFilters'
],
plugins: [
{
ptype: 'gridrestorefilters',
restoreableFilters : [
'name'
]
}
],
columns: {
defaults: {
menuDisabled: false,
sortable: true,
filter: true
},
items: [
{
text: 'name',
dataIndex: 'name'
}
//... you can have more columns of which filters cannot be restored
// (unless you add their `dataIndex` name to `restoreableFilters` array above)
]
}
//...
});
/**
This example is based on: http://docs.sencha.com/extjs/4.2.2/extjs-build/examples/history/
But I'm using hash-bang here.
Note that you probably would need to change at least `restoreState` function to better fit your needs.
Details depend on how your main Viewport looks, how many panels it has and so on.
*/
Ext.define('App.controller.Viewport', {
extend: 'Ext.app.Controller',
/**
* Last token that was registered
*
* Used to ommit needless state restore.
*/
lastRegisteredToken: null,
init: function() {
this.control({
'viewport': {
afterrender: this.afterrenderViewport
}
});
var me = this;
Ext.History.init();
Ext.History.on('change', function(token) {
me.restoreStateFromToken(token);
});
},
afterrenderViewport: function(viewport) {
// restore state from hash (initial load)
if (location.hash.length) {
this.restoreStateFromToken(location.hash);
}
},
/**
* Restore main panel state
*
* @private
*
* @param {type} panelId ID of the panel to restore.
* @param {type} panelParams Params for the panel's store.
*/
restoreState: function(panelId, panelParams) {
if (panelParams && panelParams.length) {
var view = Ext.ComponentQuery.query("#" + panelId).pop();
for (var i = 0; i<panelParams.length; i++) {
view.getStore().getProxy().extraParams[panelParams[i].name] = panelParams[i].value;
}
view.getStore().load();
}
Ext.ComponentQuery.query('#viewportCards').pop().getLayout().setActiveItem(panelId);
},
/**
* Save the viewport state.
*
* @private
*
* @param {type} panelId ID of the panel to restore.
* @param {type} panelParams Params for the panel's store.
*/
registerState: function(panelId, panelParams) {
// generate token
var newToken = '?panel='+panelId;
if (panelParams) {
for (var i = 0; i<panelParams.length; i++) {
newToken += '&'+panelParams[i].name+'='+panelParams[i].value;
}
}
// add if different
var oldToken = Ext.History.getToken();
if (oldToken === null || oldToken !== newToken) {
this.lastRegisteredToken = newToken;
Ext.History.add(newToken);
}
},
/**
* Set the viewport state.
*
* @note It also saves the state.
*
* @param {type} panelId ID of the panel to restore.
* @param {type} panelParams Params for the panel's store.
*/
setState: function(panelId, panelParams) {
this.registerState(panelId, panelParams);
this.restoreState(panelId, panelParams);
},
/**
* Restore main panel state.
*
* @private
*
* @param {String} historyToken token taken from the history.
*/
parseStateToken: function(historyToken){
var panelParams = [];
var panelId = 'mygrid'; // default panel name
if (historyToken) {
historyToken.replace(/[?&]([^=]+)=([^&]*)/g, function(a, name, value){
if (name === 'panel') {
panelId = value;
return;
}
panelParams.push({'name':name, 'value': value});
});
}
return {
panelParams: panelParams,
panelId: panelId
};
},
/**
* Restore the viewport state from token.
*
* @note If you have some menu of which state needs to you could add it's state restore call here.
*
* @param {String} token Token taken from the history or from hash (without the "#" character)
*/
restoreStateFromToken: function(token) {
if (this.lastRegisteredToken && this.lastRegisteredToken === token) {
return;
}
var stateToken = this.parseStateToken(token);
this.restoreState(stateToken.panelId, stateToken.panelParams);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment