PDA

View Full Version : GridFilters - enhanced filtering for grids



mjlecomte
30 Jul 2009, 10:43 AM
The original extension (http://extjs.com/forum/showthread.php?t=14503) has been refactored for use with Ext 3.

This version has been checked into svn (http://extjs.com/store/extjs/#support-table). I made a brief screencast, please click here (http://www.screencast.com/users/mjlecomte/folders/Jing/media/54673eae-4881-4694-9b72-67ea44562002) to see it.

A few changes / enhancements to note:

each filter may be configured via the column model (less repetition of code)
the filter query format is configurable to use json format
filters will automatically reconfigure if the grid is reconfigured
filters clean up after themselves (there was no cleanup in previous version)
filter classes utilize form fields, so you can configure the fields to use validation for example
filters may be dynamically disabled from user manipulation (still experimental)
icons are modifiable just like any other menu and css (even with IE6 -- see attachment)
complete documentation, click here (http://www.screencast.com/users/mjlecomte/folders/Jing/media/6c91107c-513d-47ba-9238-b8709b42b719)to see it.

mjlecomte
30 Jul 2009, 10:43 AM
FAQs



Where can I download or demo this extension? This extension is currently only in svn. To access svn you must be a svn subscriber (http://extjs.com/store/extjs/#support-table). This extension will be included with the ExtJS 3.1 release which is estimated to be released November 15, 2009.

renoye
30 Jul 2009, 11:53 PM
I can not find the place to do svn check out. Also, I do not know the path.

Can you zip a folder with local grid filter example that you showed? thanks a lot.

galdaka
31 Jul 2009, 1:29 AM
Excellent work!!

I hope to view in action for test it.

Greetings,

slemiere
31 Jul 2009, 1:57 AM
Hello !!

This seems to be perfect in your screencast but is there a way to get the code to test it ? Or at least have an online demo ? I didn't suscribe to svn.
Thanks a lot,

Sylvain

wiznia
31 Jul 2009, 2:14 AM
Just posting to get notifications...

galdaka
10 Aug 2009, 12:17 AM
Hi,

Excellent work.

Two small things that affect the appearance.

1) In IE there is a icon position minor error. View attached image (error1.jpg). OK in FF.

2) In IE and in FF, ".x-grid3-hd-row td.ux-filtered-column" not work as expected. When I filter one column the title not appears with css class. View error2.jpg.

Greetings,

mjlecomte
10 Aug 2009, 3:16 AM
is a known issue with textfields in menu, I believe there's an open bug report
need a test case, preferably something standalone. AFAIK the demo example provided in svn applies the css class correctly.

bernd01
12 Aug 2009, 5:12 AM
Hi!

I also really would appreciate if the 3.0 version of the filter would be available somewhere without svn? The problem is, that I am not a svn subscriber and would need filters earlier than november...

Thanks a lot,
Bernd

drieraf
12 Aug 2009, 5:29 AM
Hi!

I also really would appreciate if the 3.0 version of the filter would be available somewhere without svn? The problem is, that I am not a svn subscriber and would need filters earlier than november...

Thanks a lot,
Bernd

Hi. I'm agree with you, but I patched the old code with forum comments. I think that run correctly.



/**
* Ext.ux.grid.GridFilters v0.2.8
**/

Ext.namespace("Ext.ux.grid");
/* PATCH http://extjs.com/forum/showthread.php?t=76280 */
Ext.override(Ext.grid.GridView, {
handleHdMenuClick : function(item){
var index = this.hdCtxIndex,
cm = this.cm,
ds = this.ds,
id = item.getItemId();
switch(id){
case 'asc':
ds.sort(cm.getDataIndex(index), 'ASC');
break;
case 'desc':
ds.sort(cm.getDataIndex(index), 'DESC');
break;
default:
index = cm.getIndexById(id.substr(4));
if(index != -1){
if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
this.onDenyColumnHide();
return false;
}
cm.setHidden(index, item.checked);
}
}
return true;
}
});
/* END PATCH */
Ext.ux.grid.GridFilters = function(config){
this.filters = new Ext.util.MixedCollection();
this.filters.getKey = function(o){return o ? o.dataIndex : null};

for(var i=0, len=config.filters.length; i<len; i++)
this.addFilter(config.filters[i]);

this.deferredUpdate = new Ext.util.DelayedTask(this.reload, this);

delete config.filters;
Ext.apply(this, config);
};
Ext.extend(Ext.ux.grid.GridFilters, Ext.util.Observable, {
/**
* @cfg {Integer} updateBuffer
* Number of milisecond to defer store updates since the last filter change.
*/
updateBuffer: 500,
/**
* @cfg {String} paramPrefix
* The url parameter prefix for the filters.
*/
paramPrefix: 'filter',
/**
* @cfg {String} fitlerCls
* The css class to be applied to column headers that active filters. Defaults to 'ux-filterd-column'
*/
filterCls: 'ux-filtered-column',
/**
* @cfg {Boolean} local
* True to use Ext.data.Store filter functions instead of server side filtering.
*/
local: false,
/**
* @cfg {Boolean} autoReload
* True to automagicly reload the datasource when a filter change happens.
*/
autoReload: true,
/**
* @cfg {String} stateId
* Name of the Ext.data.Store value to be used to store state information.
*/
stateId: undefined,
/**
* @cfg {Boolean} showMenu
* True to show the filter menus
*/
showMenu: true,

menuFilterText: 'Filters',

init: function(grid){
if(grid instanceof Ext.grid.GridPanel){
this.grid = grid;

this.store = this.grid.getStore();
if(this.local){
this.store.on('load', function(store){
store.filterBy(this.getRecordFilter());
}, this);
} else {
this.store.on('beforeload', this.onBeforeLoad, this);
}

this.grid.filters = this;

this.grid.addEvents({"filterupdate": true});

grid.on("render", this.onRender, this);

grid.on("beforestaterestore", this.applyState, this);
grid.on("beforestatesave", this.saveState, this);

} else if(grid instanceof Ext.PagingToolbar){
this.toolbar = grid;
}
},

/** private **/
applyState: function(grid, state){
this.suspendStateStore = true;
this.clearFilters();
if(state.filters)
for(var key in state.filters){
var filter = this.filters.get(key);
if(filter){
filter.setValue(state.filters[key]);
filter.setActive(true);
}
}

this.deferredUpdate.cancel();
if(this.local)
this.reload();

this.suspendStateStore = false;
},

/** private **/
saveState: function(grid, state){
var filters = {};
this.filters.each(function(filter){
if(filter.active)
filters[filter.dataIndex] = filter.getValue();
});
return state.filters = filters;
},

/** private **/
onRender: function(){
var hmenu;

if(this.showMenu){
hmenu = this.grid.getView().hmenu;

this.sep = hmenu.addSeparator();
this.menu = hmenu.add(new Ext.menu.CheckItem({
text: this.menuFilterText,
menu: new Ext.menu.Menu()
}));
this.menu.on('checkchange', this.onCheckChange, this);
this.menu.on('beforecheckchange', this.onBeforeCheck, this);

hmenu.on('beforeshow', this.onMenu, this);
}

this.grid.getView().on("refresh", this.onRefresh, this);
this.updateColumnHeadings(this.grid.getView());
},

/** private **/
onMenu: function(filterMenu){
var filter = this.getMenuFilter();
if(filter){
this.menu.menu = filter.menu;
this.menu.setChecked(filter.active, false);
}

this.menu.setVisible(filter !== undefined);
this.sep.setVisible(filter !== undefined);
},

/** private **/
onCheckChange: function(item, value){
this.getMenuFilter().setActive(value);
},

/** private **/
onBeforeCheck: function(check, value){
return !value || this.getMenuFilter().isActivatable();
},

/** private **/
onStateChange: function(event, filter){
if(event == "serialize") return;

if(filter == this.getMenuFilter())
this.menu.setChecked(filter.active, false);

if(this.autoReload || this.local)
this.deferredUpdate.delay(this.updateBuffer);

var view = this.grid.getView();
this.updateColumnHeadings(view);

this.grid.saveState();

this.grid.fireEvent('filterupdate', this, filter);
},

/** private **/
onBeforeLoad: function(store, options){
options.params = options.params || {};
this.cleanParams(options.params);
var params = this.buildQuery(this.getFilterData());
Ext.apply(options.params, params);
},

/** private **/
onRefresh: function(view){
this.updateColumnHeadings(view);
},

/** private **/
getMenuFilter: function(){
var view = this.grid.getView();
if(!view || view.hdCtxIndex === undefined)
return null;

return this.filters.get(
view.cm.config[view.hdCtxIndex].dataIndex);
},

/** private **/
updateColumnHeadings: function(view){
if(!view || !view.mainHd) return;

var hds = view.mainHd.select('td').removeClass(this.filterCls);
for(var i=0, len=view.cm.config.length; i<len; i++){
var filter = this.getFilter(view.cm.config[i].dataIndex);
if(filter && filter.active)
hds.item(i).addClass(this.filterCls);
}
},

/** private **/
reload: function(){
if(this.local){
this.grid.store.clearFilter(true);
this.grid.store.filterBy(this.getRecordFilter());
} else {
this.deferredUpdate.cancel();
var store = this.grid.store;
if(this.toolbar){
var start = this.grid.getStore().paramNames.start;
if(store.lastOptions && store.lastOptions.params && store.lastOptions.params[start])
store.lastOptions.params[start] = 0;
}
store.reload();
}
},

/**
* Method factory that generates a record validator for the filters active at the time
* of invokation.
*
* @private
*/
getRecordFilter: function(){
var f = [];
this.filters.each(function(filter){
if(filter.active) f.push(filter);
});

var len = f.length;
return function(record){
for(var i=0; i<len; i++)
if(!f[i].validateRecord(record))
return false;

return true;
};
},

/**
* Adds a filter to the collection.
*
* @param {Object/Ext.ux.grid.filter.Filter} config A filter configuration or a filter object.
*
* @return {Ext.ux.grid.filter.Filter} The existing or newly created filter object.
*/
addFilter: function(config){
var filter = config.menu ? config :
new (this.getFilterClass(config.type))(config);
this.filters.add(filter);

Ext.util.Observable.capture(filter, this.onStateChange, this);
return filter;
},

/**
* Returns a filter for the given dataIndex, if on exists.
*
* @param {String} dataIndex The dataIndex of the desired filter object.
*
* @return {Ext.ux.grid.filter.Filter}
*/
getFilter: function(dataIndex){
return this.filters.get(dataIndex);
},

/**
* Turns all filters off. This does not clear the configuration information.
*/
clearFilters: function(){
this.filters.each(function(filter){
filter.setActive(false);
});
},

/** private **/
getFilterData: function(){
var filters = [],
fields = this.grid.getStore().fields;

this.filters.each(function(f){
if(f.active){
var d = [].concat(f.serialize());
for(var i=0, len=d.length; i<len; i++)
filters.push({
field: f.dataIndex,
data: d[i]
});
}
});

return filters;
},

/**
* Function to take structured filter data and 'flatten' it into query parameteres. The default function
* will produce a query string of the form:
* filters[0][field]=dataIndex&filters[0][data][param1]=param&filters[0][data][param2]=param...
*
* @param {Array} filters A collection of objects representing active filters and their configuration.
* Each element will take the form of {field: dataIndex, data: filterConf}. dataIndex is not assured
* to be unique as any one filter may be a composite of more basic filters for the same dataIndex.
*
* @return {Object} Query keys and values
*/
buildQuery: function(filters){
var p = {};
for(var i=0, len=filters.length; i<len; i++){
var f = filters[i];
var root = [this.paramPrefix, '[', i, ']'].join('');
p[root + '[field]'] = f.field;

var dataPrefix = root + '[data]';
for(var key in f.data)
p[[dataPrefix, '[', key, ']'].join('')] = f.data[key];
}

return p;
},

/**
* Removes filter related query parameters from the provided object.
*
* @param {Object} p Query parameters that may contain filter related fields.
*/
cleanParams: function(p){
var regex = new RegExp("^" + this.paramPrefix + "\[[0-9]+\]");
for(var key in p)
if(regex.test(key))
delete p[key];
},

/**
* Function for locating filter classes, overwrite this with your favorite
* loader to provide dynamic filter loading.
*
* @param {String} type The type of filter to load.
*
* @return {Class}
*/
getFilterClass: function(type){
return Ext.ux.grid.filter[type.substr(0, 1).toUpperCase() + type.substr(1) + 'Filter'];
}
});

bernd01
17 Aug 2009, 1:05 AM
Hi drieraf!

Thanks a lot! Working like a charm!

Best regards,
Bernd

astraschedule
17 Aug 2009, 6:05 PM
Looking great - especially the docs!

Q1: The config arg to the constructor seems very optional now if you want to use the column model to define your filters - sadly the constructor requires it even if it's empty...

Q2: It seems the columnModel usage of filters is limited to reconfigure? If I never reconfigure the grid, how can I get filters to come through the columnModel? Must be missing something.

As a test, I edited the init method like so:



this.grid.filters = this;

this.addFilters(grid.getColumnModel()); // added
this.updateColumnHeadings(); // added
This works, but is just a guess.

mjlecomte
17 Aug 2009, 8:04 PM
Those are bugs. I'll copy your post to the bugs forum.
http://extjs.com/forum/showthread.php?t=77892

Fabyo
25 Aug 2009, 11:19 AM
link download GridFilters?

calavera
26 Aug 2009, 9:42 AM
So no sharing without the svn ? :(

Fabyo
26 Aug 2009, 9:48 AM
Why not publish the link at once?

if it continues, with a few plugins I start using extjs 2.x

jimtyp
27 Aug 2009, 1:58 PM
Any estimate on when this Grid Filter extension will be available? I really need grid filtering but may have to go back to version 2.2 if not available by the end of next week.

jimtyp
27 Aug 2009, 2:02 PM
Ah, never mind I see it won't be available until 3.1, mid-November :-(

froamer
28 Aug 2009, 6:03 AM
I grabbed it from the Ext 3 Demo:
http://extjs.com/deploy/dev/examples/grid-filtering/grid-filter-local.html

However, I found that sorting and filtering grids with a horizontal scroll bar was a) not preserving the horizontal scroll pos and b) was not displaying the column headings correctly until after the grid was scrolled or resized.

I don't know if this is by design, a bug or an incompatibility issue with the grid filter plug-in. So I put the following together until I can investigate further. It preserves the horizontal scroll pos onload (solves both my problems). I haven't found any problems with it yet...

Ext.ux.GridViewPreserveHScroll = Ext.extend(Ext.grid.GridView, {
onLoad: function() {
//overridden to preserve the horizontal scroll position
this.scroller.dom.scrollTop = 0;
}
});
Use an instance of this as the grid view in your grid...

clicksToEdit: 1,
view: new Ext.ux.GridViewPreserveHScroll(),
loadMask: true,
...
Tested in the browsers I have: IE6, IE8, FF3.5, Chrome 2, Safari 4 (Windows)

Doesn't work in Opera 9.64 for some reason - the headings display is not corrupted, but the horizontal scroll pos is not preserved.

hankin
28 Aug 2009, 7:25 PM
How would I go about customizing this filter to work as an input box in my column header instead of as part of the column header menu? The idea is that I would like to display the filters as part of the grid.

Condor
29 Aug 2009, 2:10 AM
So you are looking for the HeaderForm plugin (http://www.extjs.com/forum/showthread.php?t=31930)?

hankin
29 Aug 2009, 5:42 PM
Thanks that points me in the right direction.

tonedeaf
6 Sep 2009, 9:52 AM
I grabbed it from the Ext 3 Demo:
http://extjs.com/deploy/dev/examples/grid-filtering/grid-filter-local.html
Thanks froamer!

Here is an assembled copy of gridfilters from the Demo page above for anyone else looking for this extension for ExtJS 3.0.0. Extract to ExtJS examples folder.

I did a few cosmetic changes:


> Replaced the default menu images:

http://img515.imageshack.us/img515/4125/filtermenu.png

> Added a header icon (instead of the green background) for filtered columns:

http://img34.imageshack.us/img34/3299/filters.png

yohnan
7 Sep 2009, 10:58 AM
Here is an assembled copy of gridfilters from the Demo page above for anyone else looking for this extension for ExtJS 3.0.0. Extract to ExtJS examples folder.


The attached 'grid-filters.zip' file is seems to be corrupt (at least on my WinXP box). Any chance you could reattach?

Condor
7 Sep 2009, 11:07 PM
The file is not corrupt. Internet Explorer just has problem downloading stuff from this forum.

Try a different browser.

yohnan
8 Sep 2009, 5:34 AM
Ah, switched to Firefox, all is well. Thanks.

Fabyo
8 Sep 2009, 5:37 AM
Added a header icon (instead of the green background) for filtered columns:

here did not show the images in the link example

renoye
28 Sep 2009, 10:25 AM
hi,mjlecomte:

I have checked out the gridfilter from svn. Everything is fine. But I have a question that how I can use coding to set some filter value and make filter activer before grid loading data. This feature used to work in the 2.x version. Just simply set value and active in the config object for a perticular filter. How can I achieve that throgh 3.0 verison?

thanks

renoye
28 Sep 2009, 11:03 AM
hi,mjlecomte:

I have checked out the gridfilter from svn. Everything is fine. But I have a question that how I can use coding to set some filter value and make filter activer before grid loading data. This feature used to work in the 2.x version. Just simply set value and active in the config object for a perticular filter. How can I achieve that throgh 3.0 verison?

thanks

acctually, once you set one filter's value and make it active before loading data.
{
type: 'list',
dataIndex: 'severity',
options: ["condition","critical","major","minor","indeterminate","info","warning"],
phpMode: true,
value: 'major',
active: true
}

the filter value displayed right in the filter menu. However, the check box is not clicked. So it means the filter is not active. How can I set the filter to be active?

mynameisyoda
2 Oct 2009, 3:01 AM
GridFilter plugin doesnt work (in local mode) if a date time column contains null values. I've posted a bug on Bugs 3.0 forum with code to reproduce the behavior and a possible fix.

ciao

mjlecomte
2 Oct 2009, 3:50 AM
@renoye and @yoda suggest you post working code for testing

tonedeaf
3 Oct 2009, 11:49 AM
I'm trying to load filters dynamically where a user could filter a grid and then save it as a "view". So, when the "view" is opened, the filters are fetched from the server and applied to the grid.

For this, I'm using the GridFilters addFilter() function and pass it a filter configuration with a value like:

[{"dataIndex":"company", "type":"string", "value":"Washington Mutual"}]The GridFilters UI gets correctly updated and the filter is applied (and sent back to the server on subsequent refreshes.)

The addFilter() function works fine with filters of type "list", "string" and "boolean" (not tested with "date" type yet).

Now, I'm facing a problem with using addFilter() function for dynamically adding "numeric" filters. For eg:

[{"dataIndex":"age", "type":"numeric", "comparison":"eq", "value":"27"}] doesn't throw any error when passed to addFilter(), but the filter is not "shown" in the UI. However, the column header background turns green (which shows that the function "tries" to apply the filter value). But the filter is never sent back to the server for subsequent refreshes.

This problem is identical to the following post for GridFilters 2.x posted an year back and the same issue is visible in the ExtJS 3.x version of the extension.
http://www.extjs.com/forum/showthread.php?p=230531#post230531

Can anyone suggest a remedy? I think its a bug in GridFilters and the issue has to do with the GridFilters RangeMenu not correctly getting updated.

Unfortunately, I'm not too familiar with the internals of the GridFilters plugin to fix this myself.

EDIT: Figured out the correct configuration format for numeric filters:

[{"dataIndex":"age", "type":"numeric", "value":{"eq":"27"}}]

calavera
6 Oct 2009, 5:38 AM
Anybody willing to share the PHP backend code for this ? The Ext 2 code for this doesn't work anymore.

Thanks.

VinylFox
6 Oct 2009, 6:24 AM
The backend code works fine for me.

RanmaSaotome
7 Oct 2009, 5:52 AM
Hello,
I had the problem that once I reconfigured my grid (especially using a new store), the pagingtoolbar was not updated any more. Maybe this problem has already been fixed, but I did not find anything in the forum so far:

Hotfix:

In GridFilters.js:



onReconfigure : function() {
this.bindStore(this.grid.getStore());
this.store.clearFilter();
this.removeAll();
this.addFilters(this.grid.getColumnModel());
this.updateColumnHeadings();
+++ if (this.toolbar) this.toolbar.bindStore(this.store, true);
},
Best wishes,

Ranma

calavera
10 Oct 2009, 12:28 AM
The backend code works fine for me.
Oh, I had "encode:true" at my setup. Changed to false. Thanks.

benmclendon
15 Oct 2009, 5:57 AM
@drieraf

Many Thanks! This worked perfectly for me with 3.0.0 code.


Hi. I'm agree with you, but I patched the old code with forum comments. I think that run correctly.



/**
* Ext.ux.grid.GridFilters v0.2.8
**/

Ext.namespace("Ext.ux.grid");
/* PATCH http://extjs.com/forum/showthread.php?t=76280 */
Ext.override(Ext.grid.GridView, {
handleHdMenuClick : function(item){
var index = this.hdCtxIndex,
cm = this.cm,
ds = this.ds,
id = item.getItemId();
switch(id){
case 'asc':
ds.sort(cm.getDataIndex(index), 'ASC');
break;
case 'desc':
ds.sort(cm.getDataIndex(index), 'DESC');
break;
default:
index = cm.getIndexById(id.substr(4));
if(index != -1){
if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
this.onDenyColumnHide();
return false;
}
cm.setHidden(index, item.checked);
}
}
return true;
}
});
/* END PATCH */
Ext.ux.grid.GridFilters = function(config){
this.filters = new Ext.util.MixedCollection();
this.filters.getKey = function(o){return o ? o.dataIndex : null};

for(var i=0, len=config.filters.length; i<len; i++)
this.addFilter(config.filters[i]);

this.deferredUpdate = new Ext.util.DelayedTask(this.reload, this);

delete config.filters;
Ext.apply(this, config);
};
Ext.extend(Ext.ux.grid.GridFilters, Ext.util.Observable, {
/**
* @cfg {Integer} updateBuffer
* Number of milisecond to defer store updates since the last filter change.
*/
updateBuffer: 500,
/**
* @cfg {String} paramPrefix
* The url parameter prefix for the filters.
*/
paramPrefix: 'filter',
/**
* @cfg {String} fitlerCls
* The css class to be applied to column headers that active filters. Defaults to 'ux-filterd-column'
*/
filterCls: 'ux-filtered-column',
/**
* @cfg {Boolean} local
* True to use Ext.data.Store filter functions instead of server side filtering.
*/
local: false,
/**
* @cfg {Boolean} autoReload
* True to automagicly reload the datasource when a filter change happens.
*/
autoReload: true,
/**
* @cfg {String} stateId
* Name of the Ext.data.Store value to be used to store state information.
*/
stateId: undefined,
/**
* @cfg {Boolean} showMenu
* True to show the filter menus
*/
showMenu: true,

menuFilterText: 'Filters',

init: function(grid){
if(grid instanceof Ext.grid.GridPanel){
this.grid = grid;

this.store = this.grid.getStore();
if(this.local){
this.store.on('load', function(store){
store.filterBy(this.getRecordFilter());
}, this);
} else {
this.store.on('beforeload', this.onBeforeLoad, this);
}

this.grid.filters = this;

this.grid.addEvents({"filterupdate": true});

grid.on("render", this.onRender, this);

grid.on("beforestaterestore", this.applyState, this);
grid.on("beforestatesave", this.saveState, this);

} else if(grid instanceof Ext.PagingToolbar){
this.toolbar = grid;
}
},

/** private **/
applyState: function(grid, state){
this.suspendStateStore = true;
this.clearFilters();
if(state.filters)
for(var key in state.filters){
var filter = this.filters.get(key);
if(filter){
filter.setValue(state.filters[key]);
filter.setActive(true);
}
}

this.deferredUpdate.cancel();
if(this.local)
this.reload();

this.suspendStateStore = false;
},

/** private **/
saveState: function(grid, state){
var filters = {};
this.filters.each(function(filter){
if(filter.active)
filters[filter.dataIndex] = filter.getValue();
});
return state.filters = filters;
},

/** private **/
onRender: function(){
var hmenu;

if(this.showMenu){
hmenu = this.grid.getView().hmenu;

this.sep = hmenu.addSeparator();
this.menu = hmenu.add(new Ext.menu.CheckItem({
text: this.menuFilterText,
menu: new Ext.menu.Menu()
}));
this.menu.on('checkchange', this.onCheckChange, this);
this.menu.on('beforecheckchange', this.onBeforeCheck, this);

hmenu.on('beforeshow', this.onMenu, this);
}

this.grid.getView().on("refresh", this.onRefresh, this);
this.updateColumnHeadings(this.grid.getView());
},

/** private **/
onMenu: function(filterMenu){
var filter = this.getMenuFilter();
if(filter){
this.menu.menu = filter.menu;
this.menu.setChecked(filter.active, false);
}

this.menu.setVisible(filter !== undefined);
this.sep.setVisible(filter !== undefined);
},

/** private **/
onCheckChange: function(item, value){
this.getMenuFilter().setActive(value);
},

/** private **/
onBeforeCheck: function(check, value){
return !value || this.getMenuFilter().isActivatable();
},

/** private **/
onStateChange: function(event, filter){
if(event == "serialize") return;

if(filter == this.getMenuFilter())
this.menu.setChecked(filter.active, false);

if(this.autoReload || this.local)
this.deferredUpdate.delay(this.updateBuffer);

var view = this.grid.getView();
this.updateColumnHeadings(view);

this.grid.saveState();

this.grid.fireEvent('filterupdate', this, filter);
},

/** private **/
onBeforeLoad: function(store, options){
options.params = options.params || {};
this.cleanParams(options.params);
var params = this.buildQuery(this.getFilterData());
Ext.apply(options.params, params);
},

/** private **/
onRefresh: function(view){
this.updateColumnHeadings(view);
},

/** private **/
getMenuFilter: function(){
var view = this.grid.getView();
if(!view || view.hdCtxIndex === undefined)
return null;

return this.filters.get(
view.cm.config[view.hdCtxIndex].dataIndex);
},

/** private **/
updateColumnHeadings: function(view){
if(!view || !view.mainHd) return;

var hds = view.mainHd.select('td').removeClass(this.filterCls);
for(var i=0, len=view.cm.config.length; i<len; i++){
var filter = this.getFilter(view.cm.config[i].dataIndex);
if(filter && filter.active)
hds.item(i).addClass(this.filterCls);
}
},

/** private **/
reload: function(){
if(this.local){
this.grid.store.clearFilter(true);
this.grid.store.filterBy(this.getRecordFilter());
} else {
this.deferredUpdate.cancel();
var store = this.grid.store;
if(this.toolbar){
var start = this.grid.getStore().paramNames.start;
if(store.lastOptions && store.lastOptions.params && store.lastOptions.params[start])
store.lastOptions.params[start] = 0;
}
store.reload();
}
},

/**
* Method factory that generates a record validator for the filters active at the time
* of invokation.
*
* @private
*/
getRecordFilter: function(){
var f = [];
this.filters.each(function(filter){
if(filter.active) f.push(filter);
});

var len = f.length;
return function(record){
for(var i=0; i<len; i++)
if(!f[i].validateRecord(record))
return false;

return true;
};
},

/**
* Adds a filter to the collection.
*
* @param {Object/Ext.ux.grid.filter.Filter} config A filter configuration or a filter object.
*
* @return {Ext.ux.grid.filter.Filter} The existing or newly created filter object.
*/
addFilter: function(config){
var filter = config.menu ? config :
new (this.getFilterClass(config.type))(config);
this.filters.add(filter);

Ext.util.Observable.capture(filter, this.onStateChange, this);
return filter;
},

/**
* Returns a filter for the given dataIndex, if on exists.
*
* @param {String} dataIndex The dataIndex of the desired filter object.
*
* @return {Ext.ux.grid.filter.Filter}
*/
getFilter: function(dataIndex){
return this.filters.get(dataIndex);
},

/**
* Turns all filters off. This does not clear the configuration information.
*/
clearFilters: function(){
this.filters.each(function(filter){
filter.setActive(false);
});
},

/** private **/
getFilterData: function(){
var filters = [],
fields = this.grid.getStore().fields;

this.filters.each(function(f){
if(f.active){
var d = [].concat(f.serialize());
for(var i=0, len=d.length; i<len; i++)
filters.push({
field: f.dataIndex,
data: d[i]
});
}
});

return filters;
},

/**
* Function to take structured filter data and 'flatten' it into query parameteres. The default function
* will produce a query string of the form:
* filters[0][field]=dataIndex&filters[0][data][param1]=param&filters[0][data][param2]=param...
*
* @param {Array} filters A collection of objects representing active filters and their configuration.
* Each element will take the form of {field: dataIndex, data: filterConf}. dataIndex is not assured
* to be unique as any one filter may be a composite of more basic filters for the same dataIndex.
*
* @return {Object} Query keys and values
*/
buildQuery: function(filters){
var p = {};
for(var i=0, len=filters.length; i<len; i++){
var f = filters[i];
var root = [this.paramPrefix, '[', i, ']'].join('');
p[root + '[field]'] = f.field;

var dataPrefix = root + '[data]';
for(var key in f.data)
p[[dataPrefix, '[', key, ']'].join('')] = f.data[key];
}

return p;
},

/**
* Removes filter related query parameters from the provided object.
*
* @param {Object} p Query parameters that may contain filter related fields.
*/
cleanParams: function(p){
var regex = new RegExp("^" + this.paramPrefix + "\[[0-9]+\]");
for(var key in p)
if(regex.test(key))
delete p[key];
},

/**
* Function for locating filter classes, overwrite this with your favorite
* loader to provide dynamic filter loading.
*
* @param {String} type The type of filter to load.
*
* @return {Class}
*/
getFilterClass: function(type){
return Ext.ux.grid.filter[type.substr(0, 1).toUpperCase() + type.substr(1) + 'Filter'];
}
});

fshort
15 Oct 2009, 8:50 AM
Any chance we can get the documentation for Ext.grid.GridFilter integrated with the core Ext API? Dont see that there in any of the versions.

mjlecomte
16 Oct 2009, 4:31 PM
Any chance we can get the documentation for Ext.grid.GridFilter integrated with the core Ext API? Dont see that there in any of the versions.

You can already see it in 3.0.1.

tonedeaf
5 Nov 2009, 3:27 AM
In GridFilters.css the CSS rule:


li.x-menu-list-item div {
display:inline;
}


causes the month picker top to go out of the container. On removing this CSS rule, the month picker drop down shows correctly.

http://img694.imageshack.us/img694/1722/monthpicker.png

roemisch
5 Nov 2009, 3:53 AM
When I set a filter in a column, I can not remove the filter again, because I can not click on the checkbox to deactivate the filter again.
Is this probably a CSS problem ? Does anyone else know that issue ?
( I am using Ext 3.0 - and I downloaded the resources from the demo page - as the 3.0 version is not available for "normal" users).
(You can see it in action with the demo account on www.ev-manager.com (http://www.ev-manager.com) - soon there will also be a www.extrails.com (http://www.extrails.com) page for the ERP System build with Ruby on Rails and Ext-JS)

And by the way: A really great plugin that is a big step forward towards a simple reporting on tables !

hexawing
11 Nov 2009, 7:10 PM
I almost have the same question with Mr. roemisch...
The checkbox can't be clicked. With FireBug, it reports:"c.itemId is undefined".
All other filters can be uncheck by empty their options, except "boolean"--it is a radio box...
I am using Ruby on Rails, too...

mrinaljena
22 Nov 2009, 9:19 AM
Hey,did anybody got above post answer?

eyetv
22 Nov 2009, 12:26 PM
I try to replace GridFilters v2.xx with GridFilters v3.xx but my code don't work with the new version



store = new Ext.data.ArrayStore({
fields:[
{name:'id' ,type:'int'},
{name:'type_document'},
{name:'code_org'},
{name:'num_compte'},
{name:'nom_cotisant'},
{name:'siret'},{name:'portefeuille'},
{name:'date_creation' ,type:'date', dateFormat: 'd-m-Y'},
{name:'code_ano'},
{name:'periode'},
{name:'etat'},
{name:'agent'},
{name:'date_traitement' ,type:'date', dateFormat: 'd-m-Y'},
{name:'commentaire'}
],
stateful : false,
pruneModifiedRecords:'true'
});



var filters = new Ext.ux.grid.GridFilters({
filters:[
{type: 'string', dataIndex: 'type_document'},
{type: 'string', dataIndex: 'code_org'},
{type: 'string', dataIndex: 'num_compte'},
{type: 'string', dataIndex: 'nom_cotisant'},
{type: 'string', dataIndex: 'siret'},
{type: 'string', dataIndex: 'portefeuille'},
{type: 'date', dataIndex: 'date_creation'},
{type: 'string', dataIndex: 'code_ano'},
{type: 'string', dataIndex: 'periode'},
{type: 'string', dataIndex: 'etat'},
{type: 'string', dataIndex: 'agent'},
{type: 'date', dataIndex: 'date_traitement'},
{type: 'string', dataIndex: 'commentaire'}
],
local : true
});



var grid = new Ext.grid.GridPanel({
id: 'tableau',autoScroll:true,
store: store,
autoExpandColumn:'commentaire',
stripeRows: false,
height:200,plugins: filters,
view: new Ext.ux.grid.BufferView({scrollDelay: false}),
title:''
});"



var colModel = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer({width: 33}),
{id:'type_document', header:'Type de document', width: 60,hidden :false, sortable:true, dataIndex: 'type_document'},
{id:'code_org', header:'code organisume', width: 50,hidden :false, sortable:true, dataIndex: 'code_org'},
{id:'num_compte', header:'N&deg; de compte', width: 120,hidden :false, sortable:true, dataIndex: 'num_compte'},
{id:'nom_cotisant', header:'Identit&eacute; du cotisant', width: 180,hidden :false, sortable:true, dataIndex: 'nom_cotisant'},
{id:'siret', header:'Siret', width: 110,hidden :false, sortable:true, dataIndex: 'siret'},
{id:'portefeuille', header:'Portefeuille', width: 60,hidden :false, sortable:true, dataIndex: 'portefeuille'},
{id:'date_creation', header:'Date de cr&eacute;ation', width: 90,hidden :false,renderer: Ext.util.Format.dateRenderer('d-m-Y'), sortable:true, dataIndex: 'date_creation'},
{id:'code_ano', header:'Anomalie(s)', width: 120,hidden :false, sortable:true, dataIndex: 'code_ano'},
{id:'periode', header:'P&eacute;riode', width: 60,hidden :false, sortable:true, dataIndex: 'periode'},
{id:'etat', header:'Etat', width: 70,hidden :false, sortable:true, dataIndex: 'etat'},
{id:'agent', header:'Gestionnaire de compte', width: 90,hidden :false, sortable:true, dataIndex: 'agent'},
{id:'date_traitement', header:'Date de traitement', width: 80,hidden :false,renderer: Ext.util.Format.dateRenderer('d-m-Y'), sortable:true, dataIndex: 'date_traitement'},
{id:'commentaire', header:'Commentaire', width: 0,hidden :false, sortable:true, dataIndex: 'commentaire'}
]);




grid.reconfigure(store,colModel);
Ext.getCmp("onglet_resultat_recherche").add(grid);
ongletsGrillesReponses.doLayout();



I have a error with "grid.reconfigure(store,colModel); "
In FireFox : ext-all-debug.js(line 63350) the grid is undefined

roemisch
23 Nov 2009, 2:38 AM
For me it finally worked with this code for GridFilters.js:




/*!
* Ext JS Library 3.0+
* Copyright(c) 2006-2009 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
*/
Ext.namespace('Ext.ux.grid');


/**
* @class Ext.ux.grid.GridFilters
* @extends Ext.util.Observable
* <p>GridFilter is a plugin (<code>ptype='gridfilters'</code>) for grids that
* allow for a slightly more robust representation of filtering than what is
* provided by the default store.</p>
* <p>Filtering is adjusted by the user using the grid's column header menu
* (this menu can be disabled through configuration). Through this menu users
* can configure, enable, and disable filters for each column.</p>
* <p><b><u>Features:</u></b></p>
* <div class="mdetail-params"><ul>
* <li><b>Filtering implementations</b> :
* <div class="sub-desc">
* Default filtering for Strings, Numeric Ranges, Date Ranges, Lists (which can
* be backed by a Ext.data.Store), and Boolean. Additional custom filter types
* and menus are easily created by extending Ext.ux.grid.filter.Filter.
* </div></li>
* <li><b>Graphical indicators</b> :
* <div class="sub-desc">
* Columns that are filtered have {@link #filterCls a configurable css class}
* applied to the column headers.
* </div></li>
* <li><b>Paging</b> :
* <div class="sub-desc">
* If specified as a plugin to the grid's configured PagingToolbar, the current page
* will be reset to page 1 whenever you update the filters.
* </div></li>
* <li><b>Automatic Reconfiguration</b> :
* <div class="sub-desc">
* Filters automatically reconfigure when the grid 'reconfigure' event fires.
* </div></li>
* <li><b>Stateful</b> :
* Filter information will be persisted across page loads by specifying a
* <code>stateId</code> in the Grid configuration.
* <div class="sub-desc">
* The filter collection binds to the
* <code>{@link Ext.grid.GridPanel#beforestaterestore beforestaterestore}</code>
* and <code>{@link Ext.grid.GridPanel#beforestatesave beforestatesave}</code>
* events in order to be stateful.
* </div></li>
* <li><b>Grid Changes</b> :
* <div class="sub-desc"><ul>
* <li>A <code>filters</code> <i>property</i> is added to the grid pointing to
* this plugin.</li>
* <li>A <code>filterupdate</code> <i>event</i> is added to the grid and is
* fired upon onStateChange completion.</li>
* </ul></div></li>
* <li><b>Server side code examples</b> :
* <div class="sub-desc"><ul>
* <li><a href="http://www.vinylfox.com/extjs/grid-filter-php-backend-code.php">PHP</a> - (Thanks VinylFox)</li>
* <li><a href="http://extjs.com/forum/showthread.php?p=77326#post77326">Ruby on Rails</a> - (Thanks Zyclops)</li>
* <li><a href="http://extjs.com/forum/showthread.php?p=176596#post176596">Ruby on Rails</a> - (Thanks Rotomaul)</li>
* <li><a href="http://www.debatablybeta.com/posts/using-extjss-grid-filtering-with-django/">Python</a> - (Thanks Matt)</li>
* <li><a href="http://mcantrell.wordpress.com/2008/08/22/extjs-grids-and-grails/">Grails</a> - (Thanks Mike)</li>
* </ul></div></li>
* </ul></div>
* <p><b><u>Example usage:</u></b></p>
* <pre><code>
var store = new Ext.data.GroupingStore({
...
});


var filters = new Ext.ux.grid.GridFilters({
autoReload: false, //don't reload automatically
local: true, //only filter locally
// filters may be configured through the plugin,
// or in the column definition within the column model configuration
filters: [{
type: 'numeric',
dataIndex: 'id'
}, {
type: 'string',
dataIndex: 'name'
}, {
type: 'numeric',
dataIndex: 'price'
}, {
type: 'date',
dataIndex: 'dateAdded'
}, {
type: 'list',
dataIndex: 'size',
options: ['extra small', 'small', 'medium', 'large', 'extra large'],
phpMode: true
}, {
type: 'boolean',
dataIndex: 'visible'
}]
});
var cm = new Ext.grid.ColumnModel([{
...
}]);


var grid = new Ext.grid.GridPanel({
ds: store,
cm: cm,
view: new Ext.grid.GroupingView(),
plugins: [filters],
height: 400,
width: 700,
bbar: new Ext.PagingToolbar({
store: store,
pageSize: 15,
plugins: [filters] //reset page to page 1 if filters change
})
});


store.load({params: {start: 0, limit: 15}});


// a filters property is added to the grid
grid.filters
* </code></pre>
*/
Ext.ux.grid.GridFilters = Ext.extend(Ext.util.Observable, {
/**
* @cfg {Boolean} autoReload
* Defaults to true, reloading the datasource when a filter change happens.
* Set this to false to prevent the datastore from being reloaded if there
* are changes to the filters. See <code>{@link updateBuffer}</code>.
*/
autoReload : true,
/**
* @cfg {Boolean} encode
* Specify true for {@link #buildQuery} to use Ext.util.JSON.encode to
* encode the filter query parameter sent with a remote request.
* Defaults to false.
*/
/**
* @cfg {Array} filters
* An Array of filters config objects. Refer to each filter type class for
* configuration details specific to each filter type. Filters for Strings,
* Numeric Ranges, Date Ranges, Lists, and Boolean are the standard filters
* available.
*/
/**
* @cfg {String} filterCls
* The css class to be applied to column headers with active filters.
* Defaults to <tt>'ux-filterd-column'</tt>.
*/
filterCls : 'ux-filtered-column',
/**
* @cfg {Boolean} local
* <tt>true</tt> to use Ext.data.Store filter functions (local filtering)
* instead of the default (<tt>false</tt>) server side filtering.
*/
local : false,
/**
* @cfg {String} menuFilterText
* defaults to <tt>'Filters'</tt>.
*/
menuFilterText : 'Filters',
/**
* @cfg {String} paramPrefix
* The url parameter prefix for the filters.
* Defaults to <tt>'filter'</tt>.
*/
paramPrefix : 'filter',
/**
* @cfg {Boolean} showMenu
* Defaults to true, including a filter submenu in the default header menu.
*/
showMenu : true,
/**
* @cfg {String} stateId
* Name of the value to be used to store state information.
*/
stateId : undefined,
/**
* @cfg {Integer} updateBuffer
* Number of milliseconds to defer store updates since the last filter change.
*/
updateBuffer : 500,


/** @private */
constructor : function (config) {
this.deferredUpdate = new Ext.util.DelayedTask(this.reload, this);
this.filters = new Ext.util.MixedCollection();
this.filters.getKey = function (o) {
return o ? o.dataIndex : null;
};
this.addFilters(config.filters);
delete config.filters;
Ext.apply(this, config);
},


/** @private */
init : function (grid) {
if (grid instanceof Ext.grid.GridPanel) {
this.grid = grid;


this.bindStore(this.grid.getStore(), true);


this.grid.filters = this;


this.grid.addEvents({'filterupdate': true});


grid.on({
scope: this,
beforestaterestore: this.applyState,
beforestatesave: this.saveState,
beforedestroy: this.destroy,
reconfigure: this.onReconfigure
});


if (grid.rendered){
this.onRender();
} else {
grid.on({
scope: this,
single: true,
render: this.onRender
});
}


} else if (grid instanceof Ext.PagingToolbar) {
this.toolbar = grid;
}
},


/**
* @private
* Handler for the grid's beforestaterestore event (fires before the state of the
* grid is restored).
* @param {Object} grid The grid object
* @param {Object} state The hash of state values returned from the StateProvider.
*/
applyState : function (grid, state) {
var key, filter;
this.applyingState = true;
this.clearFilters();
if (state.filters) {
for (key in state.filters) {
filter = this.filters.get(key);
if (filter) {
filter.setValue(state.filters[key]);
filter.setActive(true);
}
}
}
this.deferredUpdate.cancel();
if (this.local) {
this.reload();
}
delete this.applyingState;
},


/**
* Saves the state of all active filters
* @param {Object} grid
* @param {Object} state
* @return {Boolean}
*/
saveState : function (grid, state) {
var filters = {};
this.filters.each(function (filter) {
if (filter.active) {
filters[filter.dataIndex] = filter.getValue();
}
});
return (state.filters = filters);
},


/**
* @private
* Handler called when the grid is rendered
*/
onRender : function () {
this.grid.getView().on('refresh', this.onRefresh, this);
this.createMenu();
},


/**
* @private
* Handler called by the grid 'beforedestroy' event
*/
destroy : function () {
this.removeAll();
this.purgeListeners();


if(this.filterMenu){
Ext.menu.MenuMgr.unregister(this.filterMenu);
this.filterMenu.destroy();
this.filterMenu = this.menu.menu = null;
}
},


/**
* Remove all filters, permanently destroying them.
*/
removeAll : function () {
if(this.filters){
Ext.destroy.apply(Ext, this.filters.items);
// remove all items from the collection
this.filters.clear();
}
},


 
/**
* Changes the data store bound to this view and refreshes it.
* @param {Store} store The store to bind to this view
*/
bindStore : function(store, initial){
if(!initial && this.store){
if (this.local) {
store.un('load', this.onLoad, this);
} else {
store.un('beforeload', this.onBeforeLoad, this);
}
}
if(store){
if (this.local) {
store.on('load', this.onLoad, this);
} else {
store.on('beforeload', this.onBeforeLoad, this);
}
}
this.store = store;
},


/**
* @private
* Handler called when the grid reconfigure event fires
*/
onReconfigure : function () {
this.bindStore(this.grid.getStore());
this.store.clearFilter();
this.removeAll();
this.addFilters(this.grid.getColumnModel());
this.updateColumnHeadings();
},


createMenu : function () {
var view = this.grid.getView(),
hmenu = view.hmenu;


if (this.showMenu && hmenu) {


this.sep = hmenu.addSeparator();
this.filterMenu = new Ext.menu.Menu({
id: this.grid.id + '-filters-menu'
});
this.menu = hmenu.add({
checked: false,
itemId: 'filters',
text: this.menuFilterText,
menu: this.filterMenu
});


this.menu.on({
scope: this,
checkchange: this.onCheckChange,
beforecheckchange: this.onBeforeCheck
});
hmenu.on('beforeshow', this.onMenu, this);
}
this.updateColumnHeadings();
},


/**
* @private
* Get the filter menu from the filters MixedCollection based on the clicked header
*/
getMenuFilter : function () {
var view = this.grid.getView();
if (!view || view.hdCtxIndex === undefined) {
return null;
}
return this.filters.get(
view.cm.config[view.hdCtxIndex].dataIndex
);
},


/**
* @private
* Handler called by the grid's hmenu beforeshow event
*/
onMenu : function (filterMenu) {
var filter = this.getMenuFilter();


if (filter) {
/*
TODO: lazy rendering
if (!filter.menu) {
filter.menu = filter.createMenu();
}
*/
this.menu.menu = filter.menu;
this.menu.setChecked(filter.active, false);
// disable the menu if filter.disabled explicitly set to true
this.menu.setDisabled(filter.disabled === true);
}


this.menu.setVisible(filter !== undefined);
this.sep.setVisible(filter !== undefined);
},


/** @private */
onCheckChange : function (item, value) {
this.getMenuFilter().setActive(value);
},


/** @private */
onBeforeCheck : function (check, value) {
return !value || this.getMenuFilter().isActivatable();
},


/**
* @private
* Handler for all events on filters.
* @param {String} event Event name
* @param {Object} filter Standard signature of the event before the event is fired
*/
onStateChange : function (event, filter) {
if (event === 'serialize') {
return;
}


if (filter == this.getMenuFilter()) {
this.menu.setChecked(filter.active, false);
}


if ((this.autoReload || this.local) && !this.applyingState) {
this.deferredUpdate.delay(this.updateBuffer);
}
this.updateColumnHeadings();


if (!this.applyingState) {
this.grid.saveState();
}
this.grid.fireEvent('filterupdate', this, filter);
},


/**
* @private
* Handler for store's beforeload event when configured for remote filtering
* @param {Object} store
* @param {Object} options
*/
onBeforeLoad : function (store, options) {
options.params = options.params || {};
this.cleanParams(options.params);
var params = this.buildQuery(this.getFilterData());
Ext.apply(options.params, params);
},


/**
* @private
* Handler for store's load event when configured for local filtering
* @param {Object} store
* @param {Object} options
*/
onLoad : function (store, options) {
store.filterBy(this.getRecordFilter());
},


/**
* @private
* Handler called when the grid's view is refreshed
*/
onRefresh : function () {
this.updateColumnHeadings();
},


/**
* Update the styles for the header row based on the active filters
*/
updateColumnHeadings : function () {
var view = this.grid.getView(),
hds, i, len, filter;
if (view.mainHd) {
hds = view.mainHd.select('td').removeClass(this.filterCls);
for (i = 0, len = view.cm.config.length; i < len; i++) {
filter = this.getFilter(view.cm.config[i].dataIndex);
if (filter && filter.active) {
hds.item(i).addClass(this.filterCls);
}
}
}
},


/** @private */
reload : function () {
if (this.local) {
this.grid.store.clearFilter(true);
this.grid.store.filterBy(this.getRecordFilter());
} else {
var start,
store = this.grid.store;
this.deferredUpdate.cancel();
if (this.toolbar) {
start = store.paramNames.start;
if (store.lastOptions && store.lastOptions.params && store.lastOptions.params[start]) {
store.lastOptions.params[start] = 0;
}
}
store.reload();
}
},


/**
* Method factory that generates a record validator for the filters active at the time
* of invokation.
* @private
*/
getRecordFilter : function () {
var f = [], len, i;
this.filters.each(function (filter) {
if (filter.active) {
f.push(filter);
}
});


len = f.length;
return function (record) {
for (i = 0; i < len; i++) {
if (!f[i].validateRecord(record)) {
return false;
}
}
return true;
};
},


/**
* Adds a filter to the collection and observes it for state change.
* @param {Object/Ext.ux.grid.filter.Filter} config A filter configuration or a filter object.
* @return {Ext.ux.grid.filter.Filter} The existing or newly created filter object.
*/
addFilter : function (config) {
var Cls = this.getFilterClass(config.type),
filter = config.menu ? config : (new Cls(config));
this.filters.add(filter);


Ext.util.Observable.capture(filter, this.onStateChange, this);
return filter;
},


/**
* Adds filters to the collection.
* @param {Array/Ext.grid.ColumnModel} filters Either an Array of
* filter configuration objects or an Ext.grid.ColumnModel. The columns
* of a passed Ext.grid.ColumnModel will be examined for a <code>filter</code>
* property and, if present, will be used as the filter configuration object.
*/
addFilters : function (filters) {
if (filters) {
var i, len, filter, cm = false, dI;
if (filters instanceof Ext.grid.ColumnModel) {
filters = filters.config;
cm = true;
}
for (i = 0, len = filters.length; i < len; i++) {
filter = false;
if (cm) {
dI = filters[i].dataIndex;
filter = filters[i].filter || filters[i].filterable;
if (filter){
filter = (filter === true) ? {} : filter;
Ext.apply(filter, {dataIndex:dI});
// filter type is specified in order of preference:
// filter type specified in config
// type specified in store's field's type config
filter.type = filter.type || this.store.fields.get(dI).type;
}
} else {
filter = filters[i];
}
// if filter config found add filter for the column
if (filter) {
this.addFilter(filter);
}
}
}
},


/**
* Returns a filter for the given dataIndex, if one exists.
* @param {String} dataIndex The dataIndex of the desired filter object.
* @return {Ext.ux.grid.filter.Filter}
*/
getFilter : function (dataIndex) {
return this.filters.get(dataIndex);
},


/**
* Turns all filters off. This does not clear the configuration information
* (see {@link #removeAll}).
*/
clearFilters : function () {
this.filters.each(function (filter) {
filter.setActive(false);
});
},


/**
* Returns an Array of the currently active filters.
* @return {Array} filters Array of the currently active filters.
*/
getFilterData : function () {
var filters = [], i, len;


this.filters.each(function (f) {
if (f.active) {
var d = [].concat(f.serialize());
for (i = 0, len = d.length; i < len; i++) {
filters.push({
field: f.dataIndex,
data: d[i]
});
}
}
});
return filters;
},


/**
* Function to take the active filters data and build it into a query.
* The format of the query depends on the <code>{@link #encode}</code>
* configuration:
* <div class="mdetail-params"><ul>
*
* <li><b><tt>false</tt></b> : <i>Default</i>
* <div class="sub-desc">
* Flatten into query string of the form (assuming <code>{@link #paramPrefix}='filters'</code>:
* <pre><code>
filters[0][field]="someDataIndex"&
filters[0][data][comparison]="someValue1"&
filters[0][data][type]="someValue2"&
filters[0][data][value]="someValue3"&
* </code></pre>
* </div></li>
* <li><b><tt>true</tt></b> :
* <div class="sub-desc">
* JSON encode the filter data
* <pre><code>
filters[0][field]="someDataIndex"&
filters[0][data][comparison]="someValue1"&
filters[0][data][type]="someValue2"&
filters[0][data][value]="someValue3"&
* </code></pre>
* </div></li>
* </ul></div>
* Override this method to customize the format of the filter query for remote requests.
* @param {Array} filters A collection of objects representing active filters and their configuration.
* Each element will take the form of {field: dataIndex, data: filterConf}. dataIndex is not assured
* to be unique as any one filter may be a composite of more basic filters for the same dataIndex.
* @return {Object} Query keys and values
*/
buildQuery : function (filters) {
var p = {}, i, f, root, dataPrefix, key, tmp,
len = filters.length;


if (!this.encode){
for (i = 0; i < len; i++) {
f = filters[i];
root = [this.paramPrefix, '[', i, ']'].join('');
p[root + '[field]'] = f.field;


dataPrefix = root + '[data]';
for (key in f.data) {
p[[dataPrefix, '[', key, ']'].join('')] = f.data[key];
}
}
} else {
tmp = [];
for (i = 0; i < len; i++) {
f = filters[i];
tmp.push(Ext.apply(
{},
{field: f.field},
f.data
));
}
// only build if there is active filter
if (tmp.length > 0){
p[this.paramPrefix] = Ext.util.JSON.encode(tmp);
}
}
return p;
},


/**
* Removes filter related query parameters from the provided object.
* @param {Object} p Query parameters that may contain filter related fields.
*/
cleanParams : function (p) {
// if encoding just delete the property
if (this.encode) {
delete p[this.paramPrefix];
// otherwise scrub the object of filter data
} else {
var regex, key;
regex = new RegExp('^' + this.paramPrefix + '\[[0-9]+\]');
for (key in p) {
if (regex.test(key)) {
delete p[key];
}
}
}
},


/**
* Function for locating filter classes, overwrite this with your favorite
* loader to provide dynamic filter loading.
* @param {String} type The type of filter to load ('Filter' is automatically
* appended to the passed type; eg, 'string' becomes 'StringFilter').
* @return {Class} The Ext.ux.grid.filter.Class
*/
getFilterClass : function (type) {
// map the supported Ext.data.Field type values into a supported filter
switch(type) {
case 'auto':
type = 'string';
break;
case 'int':
case 'float':
type = 'numeric';
break;
}
return Ext.ux.grid.filter[type.substr(0, 1).toUpperCase() + type.substr(1) + 'Filter'];
}
});


// register ptype
Ext.preg('gridfilters', Ext.ux.grid.GridFilters);

westy
22 Dec 2009, 6:45 AM
FAQs



Where can I download or demo this extension? This extension is currently only in svn. To access svn you must be a svn subscriber (http://extjs.com/store/extjs/#support-table). This extension will be included with the ExtJS 3.1 release which is estimated to be released November 15, 2009.


Hmm, is this really the case?

I can't see it in the API Docs (http://www.extjs.com/deploy/dev/docs/) :s

Cheers,
Westy

Condor
22 Dec 2009, 10:07 PM
Hmm, is this really the case?

I can't see it in the API Docs (http://www.extjs.com/deploy/dev/docs/) :s

Cheers,
Westy

It's included as an example (which unfortunately aren't in the API docs).

westy
23 Dec 2009, 1:28 AM
Ah ok, thanks Condor :)

dtex-lab
30 Dec 2009, 1:54 AM
Hi
I'm using extjs 3.1 and I need to extends/override the base
Ext.ux.grid.GridFilters in order to intercept filter and apply my business logic instead of the standard one when the user apply the filter (in my case I need to avoid local filter and execute an ajax request.. )

To do it I override the onStateChange function


onStateChange : function (event, filter)


and it is working fine for "StringFilter": when the the user push the enter button, the onStateChange event is called once with "event" = "activate"

But when I have a BooleanFilter, my extension doesn't works
the onStateChange event is called 3 times

the first with event "activate", the 2nd and 3th time with event 'update'
Only the lastest time the getValue() function on filter contains the right value...

So probably I override the wrong function...

What is the right one ?

I have also another requirement on the ListFilter
At this time the event is throws every time a user select an item.
Instead I want thows the event only when the user push the enter button
This is because I need to send a remote request... and so I must wait that the user finish to select items..

Thanks

stalek
6 Jan 2010, 2:34 AM
I have 6 params on my DirectStore. When any filter is not enabled (I use JSON encoding feature) the "onBeforeLoad" method removes "filter" parameter from parameters list and it's not reconstructed/added later in "buildQuery" method.

Because of this I receive exception "Parameter count mismatch." during call. It's because "filter" parameter is missing (has been removed from parameters list). The method called by DirectPrivider (.net version) has such signature:


public MessageResult GetMessages(long start, long limit, string sort, string dir, string filter, string clientAppId)

I was trying to avoid the problem adding method with overloaded parameters list like below, but DirectAction object uses Dictionary to store info about method names for methods it can call so we can't create two methods with the same name but with different parameters list.



[DirectMethod]
// There is NO filter parameter here !!!
public MessageResult GetMessages(long start, long limit, string sort, string dir, string clientAppId)
{
return GetMessages(start, limit, sort, dir,null, clientAppId);
}

Temporary I resolved the problem modifying the condition at the end of "buildQuery" method in GridFilters.js file.

The old version was like this:



// only build if there is active filter
if (tmp.length > 0){
p[this.paramPrefix] = Ext.util.JSON.encode(tmp);
}

My new version has "else" clause like in the code below:


// only build if there is active filter
if (tmp.length > 0){
p[this.paramPrefix] = Ext.util.JSON.encode(tmp);
}
else
p[this.paramPrefix] = null;


Maybe somebody knows better solution...

It worked quite well with version 3.0 (then I received null value on "filter" parameter and order and amount of parameters was proper).

I don't see significant changes in GridFilters.js file between versions 3.0 and 3.1 ...

SunWuKung
21 Jan 2010, 7:58 AM
Hi,
I would need to display labels and use ids in my list filter.
I have tried this, but it sends strange values to the server:
{
type: 'list',
dataIndex: 'ref_lifecycle',
options: [{'id':'active', 'text':'Aktív'},{'id':'inactive', 'text':'Inaktív'}],
labelField:'text',
phpMode: true
}

I have also tried to use store, but I always get a javascript proxy error.
Could somebody tell me how to do this?

Many thanks.
SWK

------
Ok, I have found the solution for this its:
options:[['active', 'sometext1'], ['some_closed', 'sometext2']]

brookd
25 Jan 2010, 2:02 PM
When I call filters.clearFilters(), all of the filters are removed correctly, including header classes and the generated query strings, however, the checkboxes in my list filter never get cleared. I added the following to resolve this:

In ListMenu.js:


clearSelected: function(){
if (this.loaded) {
this.items.each(function(item){
item.setChecked(false, true);
}, this);
}
}


and in ListFilter.js. in the init method, I added:



this.on('deactivate', this.menu.clearSelected,this.menu);


Maybe, there is a better, way, however, this seems to work :)

tonedeaf
27 Jan 2010, 8:59 AM
however, the checkboxes in my list filter never get cleared.

You can also clear them by adding the line below (in bold) to the clearFilters() function:


/**
* Turns all filters off. This does not clear the configuration information
* (see {@link #removeAll}).
*/
clearFilters : function () {
this.filters.each(function (filter) {
filter.setActive(false);
filter.setValue('');
});
},

Scorpie
28 Jan 2010, 5:26 AM
Nice work, these kind of filters gives some true strength!

DerSalz
29 Jan 2010, 6:51 AM
The grid filter is a cool feature but I think the behaviour of the PagingToolbar in the example is not correct:

Ich expect the PagingToolbar to recalculate the actual needed pages after filtering. You can check this easily by changing the page-size to 10 in the example and then filter for example the "company" field by "3m". There will be only one entry which is right but the paging toolbar still shows 3 pages!

What has to be done that filtering and paging works together?

Or am I doing something wrong?

Thanx

asbestos girl
9 Feb 2010, 6:05 AM
I have the same problem as DerSalz - that is when doing local filtering. Moreover, when doing local filtering, one must use PagingStore. But even so, the page count problem is still there. The page count corrects itself when you refresh the store usign the refresh button in the paging toolbar, but this should happen automagically whenever the filter is updated

-----------------------------------------------------

Another problem i have discovered is this:
if the page where i use GridFilters, also contains any menu, that contains a combobox, then in Firefox my combobox inside a menu does not display correctly:

This is what it should look like:

http://lh6.ggpht.com/_IYlWLa8dbMM/S3FqBacfYaI/AAAAAAAADd8/Tg1bytMLgg4/Menu%20combo%20okay.jpg

But it looks like this:

http://lh6.ggpht.com/_IYlWLa8dbMM/S3FqBZKHlRI/AAAAAAAADd4/SbvjExwc3Jk/Menu%20combo%20broken.jpg

and the css that causes this is in GridFilters.css:


/* Temporary Patch for Bug ??? */
.x-menu-list-item-indent .x-menu-item-icon {
position: relative;
top: 3px;
left: 3px;
margin-right: 10px;
}
li.x-menu-list-item-indent {
padding-left:0px;
}
li.x-menu-list-item div {
display: inline;
}However I cannot comment this block of css out either, because it is needed for correct rendering of numeric filter menus:

http://lh3.ggpht.com/_IYlWLa8dbMM/S3FqBimDXMI/AAAAAAAADeE/DD3InHFTOKA/numeric%20okay.jpg

When i comment the conflicting css rules out, I get this:

http://lh4.ggpht.com/_IYlWLa8dbMM/S3FqBgPEQ2I/AAAAAAAADeA/S5-EKL0Phg4/numeric%20broken.jpg

mx_starter
11 Feb 2010, 9:48 AM
It's included as an example (which unfortunately aren't in the API docs).

So, i've found a couple of request for API-style documentation.

http://extjs-ux.org/ext-docs/

This is the most actual source for ux API docs we must observe, right?
Just want to be clear.
Thanks.

calavera
22 Feb 2010, 8:53 AM
Hello. I would need some help, if wanted: I have a list type of filter on one of my grids and whenever I choose two options from the list, I can't get results from both of them options. I have studied the POST with Firebug and I have noticed that the grid posts like this:


filter[0][data][type] list
filter[0][data][value] 3
filter[0][data][value] 1
filter[0][field] package


and my filter config for this:


type: 'list',
dataIndex: 'package',
store: storePackage,
labelField: 'package',
single: false


storePackage store like this:


var storePackage = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url: 'index.php/requests/getPackages'}),
reader: new Ext.data.JsonReader({ root: 'rows' }, [{ name: 'id' }, { name: 'package'}])
,baseParams:{cmd:'getPackages',id:null}
});


If you notice, the filter POSTs from the list, the value postss from the filter, have two values have the same index "0" on both of them...so in my PHP I can only process one value from it... Anybody else got this ?

tonedeaf
23 Feb 2010, 12:12 AM
Specify phpMode: true in the filter config


{
type: 'list',
dataIndex: 'size',
options: ['extra small', 'small', 'medium', 'large', 'extra large'],
phpMode: true
}

digitalkaoz
23 Feb 2010, 2:40 AM
he i think ive found a workaround for the pagingtoolbar filtering problem:

in my store beforeload function i simpy set the page to 0 if ther filters has changed:



/** Store **/
listeners:{
beforeload : {fn:function(){
if(this.filterHasChanged){
this.setBaseParam('start',0);
if(this.lastOptions && this.lastOptions.params){
this.lastOptions.params.start = 0;
}
}
},scope:this},
load: {fn: function(){this.filterHasChanged=false;},scope:this}
}

this.filterHasChanged is set manually by the grid event "filterupdate" which comes with the grid filters plugin



/** GridPanel**/
listeners:{
filterupdate: {fn:function(){this.getStore().filterHasChanged=true;}, scope:this}
}

and now voila...if im on page X and filter my results, the paging toolbar and the whole grid will jump back to page 1.

cost me a lot of hairs ;)

calavera
24 Feb 2010, 6:39 AM
Specify phpMode: true in the filter config


{
type: 'list',
dataIndex: 'size',
options: ['extra small', 'small', 'medium', 'large', 'extra large'],
phpMode: true
}

Oh, I totally forgot about this. Thank you! It works great.

blueberrymuffins
24 Feb 2010, 9:44 AM
Hi, I am new to extjs and I am attempting to modify the grid filter example that comes with 3.1.1 to work with a java backend. I use the buildQuery function outlined in this post http://www.extjs.com/forum/showthread.php?t=52655. In my tests I am consistently getting empty arraylists passed to the jsp file.

Any help on this issue would be greatly appreciated.

Here is my code

grid-filter-local.js (modified from the file of the same name found in the examples that come with 3.1.1)

Ext.onReady(function(){

Ext.QuickTips.init();

// for this demo configure local and remote urls for demo purposes
var url = {
local: 'grid-filter.json', // static data file
remote: 'grid-filter.jsp'
};

// configure whether filter query is encoded or not (initially)
var encode = false;

// configure whether filtering is performed locally or remotely (initially)
var local = false;

store = new Ext.data.JsonStore({
// store configs
autoDestroy: true,
url: (local ? url.local : url.remote),
remoteSort: false,
sortInfo: {
field: 'company',
direction: 'ASC'
},
storeId: 'myStore',

// reader configs
idProperty:'id',
root:'data',
totalProperty:'total',
fields:[
{name:'id'},
{name:'company'},
{name:'price',type:'float'},
{name:'date',type:'date',dateFormat:'Y-m-d H:i:s'},
{name:'visible',type:'boolean'},
{name:'size'}
]
});

var filters = new Ext.ux.grid.GridFilters({
// encode and local configuration options defined previously for easier reuse
//encode: encode, // json encode the filter query
local: local, // defaults to false (remote filtering)
filters: [
{type: 'numeric',dataIndex: 'id'},
{type: 'string',dataIndex: 'company'},
{type: 'numeric', dataIndex: 'price'},
{type: 'date', dataIndex: 'date'},
{type: 'list',dataIndex: 'size', options: ['small', 'medium', 'large', 'extra large']},
{type: 'boolean', dataIndex: 'visible'}
],
buildQuery: function(filters){
var processed_filters = []

for(var i=0; i<filters.length; i++) {

var pf = {}
var filter = filters[i];

pf['field'] = filter.field;
pf['data'] = {}

for(var key in filter.data) {
pf['data'][key] = filter.data[key];
}

processed_filters.push(pf);

}

return {q: Ext.encode(processed_filters), f: filters[0]};
//return p;
}
});

// use a factory method to reduce code while demonstrating
// that the GridFilter plugin may be configured with or without
// the filter types (the filters may be specified on the column model
var createColModel = function (finish, start) {

var columns = [{
dataIndex: 'id',
header: 'Id',
// instead of specifying filter config just specify filterable=true
// to use store's field's type property (if type property not
// explicitly specified in store config it will be 'auto' which
// GridFilters will assume to be 'StringFilter'
filterable: true
//,filter: {type: 'numeric'}
}, {
dataIndex: 'company',
header: 'Company',
id: 'company',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'price',
header: 'Price',
filter: {
//type: 'numeric' // specify type here or in store fields config
}
}, {
dataIndex: 'size',
header: 'Size',
filter: {
type: 'list',
options: ['small', 'medium', 'large', 'extra large']
//,phpMode: true
}
}, {
dataIndex: 'date',
header: 'Date',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
filter: {
//type: 'date' // specify type here or in store fields config
}
}, {
dataIndex: 'visible',
header: 'Visible',
filter: {
//type: 'boolean' // specify type here or in store fields config
}
}];

return new Ext.grid.ColumnModel({
columns: columns.slice(start || 0, finish),
defaults: {
sortable: true
}
});
};

var grid = new Ext.grid.GridPanel({
border: false,
store: store,
colModel: createColModel(4),
loadMask: true,
plugins: [filters],
autoExpandColumn: 'company',
listeners: {
render: {
fn: function(){
store.load({
params: {
start: 0,
limit: 50
}
});
}
}
},
bbar: new Ext.PagingToolbar({
store: store,
pageSize: 50,
plugins: [filters]
})
});

// add some buttons to bottom toolbar just for demonstration purposes
grid.getBottomToolbar().add([
'->',
{
text: 'Encode: ' + (encode ? 'On' : 'Off'),
tooltip: 'Toggle Filter encoding on/off',
enableToggle: true,
handler: function (button, state) {
var encode = (grid.filters.encode===true) ? false : true;
var text = 'Encode: ' + (encode ? 'On' : 'Off');
// remove the prior parameters from the last load options
grid.filters.cleanParams(grid.getStore().lastOptions.params);
grid.filters.encode = encode;
button.setText(text);
grid.getStore().reload();
}
},{
text: 'Local Filtering: ' + (local ? 'On' : 'Off'),
tooltip: 'Toggle Filtering between remote/local',
enableToggle: true,
handler: function (button, state) {
var local = (grid.filters.local===true) ? false : true;
var text = 'Local Filtering: ' + (local ? 'On' : 'Off');
var newUrl = local ? url.local : url.remote;

// update the GridFilter setting
grid.filters.local = local;
// bind the store again so GridFilters is listening to appropriate store event
grid.filters.bindStore(grid.getStore());
// update the url for the proxy
grid.getStore().proxy.setApi('read', newUrl);

button.setText(text);
grid.getStore().reload();
}
},{
text: 'All Filter Data',
tooltip: 'Get Filter Data for Grid',
handler: function () {
var data = Ext.encode(grid.filters.getFilterData());
Ext.Msg.alert('All Filter Data',data);
}
},{
text: 'Clear Filter Data',
handler: function () {
grid.filters.clearFilters();
}
},{
text: 'Reconfigure Grid',
handler: function () {
grid.reconfigure(store, createColModel(6));
}
}
]);

var win = new Ext.Window({
title: 'Grid Filters Example',
height: 400,
width: 700,
layout: 'fit',
items: grid
}).show();

});

grid-filter.jsp
(just some println statements to test what is being passed through)

<%@page import="java.util.ArrayList"%>
<%@page import="org.json.simple.JSONValue"%>

<%
String start = request.getParameter("start");
String limit = request.getParameter("limit");
String sort = request.getParameter("sort");
String dir = request.getParameter("dir");

System.out.println("start= " + start);
System.out.println("limit= " + limit);
System.out.println("sort= "+sort);
System.out.println("dir= "+dir);

if (request.getParameter("q") != null && !request.getParameter("q").equals("")) {
String filter = (String) request.getParameter("q");
ArrayList filters = (ArrayList) JSONValue.parse(filter);
System.out.println("filter = " + filter);
System.out.println("filters= " + filters);
System.out.println("f= " + request.getParameter("f"));
} else {
System.out.println("error getting parameter q");
}


%>

Result:

start= 0
limit= 50
sort= null
dir= null
filter = []
filters= []
f=

Thanks again for any help

nickweavers
24 Feb 2010, 2:32 PM
FAQs



Where can I download or demo this extension? This extension is currently only in svn. To access svn you must be a svn subscriber (http://extjs.com/store/extjs/#support-table). This extension will be included with the ExtJS 3.1 release which is estimated to be released November 15, 2009.


I am using 3.1.1 but I could not find this excellent extension anywhere. In fact the whole ux branch in the 3.1.1 API webpage's tree menu isn't there. Is it still being worked on and is there a still a plan to include it sometime in the future?

TIA,
Nick.

mcouillard
25 Feb 2010, 5:08 AM
I am using 3.1.1 but I could not find this excellent extension anywhere. In fact the whole ux branch in the 3.1.1 API webpage's tree menu isn't there. Is it still being worked on and is there a still a plan to include it sometime in the future?

TIA,
Nick.


I ran into a similar confusing situation yesterday. The GridFilter plugin can be found within Ext 3.1.1 here:

/examples/ux/gridfilters/

Along with a very helpful example (look at all those includes!) found here:

/examples/grid-filtering/

And the "ux" branch of the Ext doc can be found here on the UX repository website:

http://extjs-ux.org/ext-docs/

httpdotcom
25 Feb 2010, 6:53 AM
And the "ux" branch of the Ext doc can be found here on the UX repository website:

http://extjs-ux.org/ext-docs/

Unfortunately, the documentation for GridFilters on extjs-ux.org hasn't been updated since 2008. Would be extremely helpful to get that updated, or get the ux tree item (for officially "blessed" extensions like GridFilters and Multiselect/Itemselect) restored to the docs.

tonedeaf
25 Feb 2010, 7:15 AM
ExtJS 3.0.3 has the API documentation for the user extensions. You can download it from this link:
http://www.extjs.com/deploy/ext-3.0.3.zip

They stopped including the docs for the UX from version 3.1 onwards

tonedeaf
25 Feb 2010, 7:21 AM
he i think ive found a workaround for the pagingtoolbar filtering problem:

in my store beforeload function i simpy set the page to 0 if ther filters has changed:
and now voila...if im on page X and filter my results, the paging toolbar and the whole grid will jump back to page 1.

cost me a lot of hairs ;)
For reference and for other users facing this issue, Grid filters can sync with the paging toolbar when you pass a reference to it in the paging toolbar's plugins config.

You can also look at this same issue resolved in the bugs section:
http://www.extjs.com/forum/showthread.php?t=90753

blueberrymuffins
25 Feb 2010, 11:10 AM
Hi, I am new to extjs and am attempting to use this filtering plugin with a java backend. I used the advice of this post http://www.extjs.com/forum/showthread.php?t=52655 and overrode the buildQuery function in the js file as follows


Ext.onReady(function(){

Ext.QuickTips.init();

// for this demo configure local and remote urls for demo purposes
var url = {
local: 'grid-filter.json', // static data file
remote: 'grid-filter.jsp'
};

// configure whether filter query is encoded or not (initially)
var encode = false;

// configure whether filtering is performed locally or remotely (initially)
var local = false;

store = new Ext.data.JsonStore({
// store configs
autoDestroy: true,
url: (local ? url.local : url.remote),
remoteSort: false,
sortInfo: {
field: 'company',
direction: 'ASC'
},
storeId: 'myStore',

// reader configs
idProperty:'id',
root:'data',
totalProperty:'total',
fields:[
{name:'id'},
{name:'company'},
{name:'price',type:'float'},
{name:'date',type:'date',dateFormat:'Y-m-d H:i:s'},
{name:'visible',type:'boolean'},
{name:'size'}
]
});

var filters = new Ext.ux.grid.GridFilters({
// encode and local configuration options defined previously for easier reuse
//encode: encode, // json encode the filter query
local: local, // defaults to false (remote filtering)
filters: [
{type: 'numeric',dataIndex: 'id'},
{type: 'string',dataIndex: 'company'},
{type: 'numeric', dataIndex: 'price'},
{type: 'date', dataIndex: 'date'},
{type: 'list',dataIndex: 'size', options: ['small', 'medium', 'large', 'extra large']},
{type: 'boolean', dataIndex: 'visible'}
],
buildQuery: function(filters){
var processed_filters = []

for(var i=0; i<filters.length; i++) {

var pf = {}
var filter = filters[i];

pf['field'] = filter.field;
pf['data'] = {}

for(var key in filter.data) {
pf['data'][key] = filter.data[key];
}

processed_filters.push(pf);

}

return {q: Ext.encode(processed_filters), f: filters[0], f2: filters[1]};
//return p;
}
});

// use a factory method to reduce code while demonstrating
// that the GridFilter plugin may be configured with or without
// the filter types (the filters may be specified on the column model
var createColModel = function (finish, start) {

var columns = [{
dataIndex: 'id',
header: 'Id',
// instead of specifying filter config just specify filterable=true
// to use store's field's type property (if type property not
// explicitly specified in store config it will be 'auto' which
// GridFilters will assume to be 'StringFilter'
filterable: true
//,filter: {type: 'numeric'}
}, {
dataIndex: 'company',
header: 'Company',
id: 'company',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'price',
header: 'Price',
filter: {
//type: 'numeric' // specify type here or in store fields config
}
}, {
dataIndex: 'size',
header: 'Size',
filter: {
type: 'list',
options: ['small', 'medium', 'large', 'extra large']
//,phpMode: true
}
}, {
dataIndex: 'date',
header: 'Date',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
filter: {
//type: 'date' // specify type here or in store fields config
}
}, {
dataIndex: 'visible',
header: 'Visible',
filter: {
//type: 'boolean' // specify type here or in store fields config
}
}];

return new Ext.grid.ColumnModel({
columns: columns.slice(start || 0, finish),
defaults: {
sortable: true
}
});
};

var grid = new Ext.grid.GridPanel({
border: false,
store: store,
colModel: createColModel(4),
loadMask: true,
plugins: [filters],
autoExpandColumn: 'company',
listeners: {
render: {
fn: function(){
store.load({
params: {
start: 0,
limit: 50
}
});
}
}
},
bbar: new Ext.PagingToolbar({
store: store,
pageSize: 50,
plugins: [filters]
})
});

// add some buttons to bottom toolbar just for demonstration purposes
grid.getBottomToolbar().add([
'->',
{
text: 'Encode: ' + (encode ? 'On' : 'Off'),
tooltip: 'Toggle Filter encoding on/off',
enableToggle: true,
handler: function (button, state) {
var encode = (grid.filters.encode===true) ? false : true;
var text = 'Encode: ' + (encode ? 'On' : 'Off');
// remove the prior parameters from the last load options
grid.filters.cleanParams(grid.getStore().lastOptions.params);
grid.filters.encode = encode;
button.setText(text);
grid.getStore().reload();
}
},{
text: 'Local Filtering: ' + (local ? 'On' : 'Off'),
tooltip: 'Toggle Filtering between remote/local',
enableToggle: true,
handler: function (button, state) {
var local = (grid.filters.local===true) ? false : true;
var text = 'Local Filtering: ' + (local ? 'On' : 'Off');
var newUrl = local ? url.local : url.remote;

// update the GridFilter setting
grid.filters.local = local;
// bind the store again so GridFilters is listening to appropriate store event
grid.filters.bindStore(grid.getStore());
// update the url for the proxy
grid.getStore().proxy.setApi('read', newUrl);

button.setText(text);
grid.getStore().reload();
}
},{
text: 'All Filter Data',
tooltip: 'Get Filter Data for Grid',
handler: function () {
var data = Ext.encode(grid.filters.getFilterData());
Ext.Msg.alert('All Filter Data',data);
}
},{
text: 'Clear Filter Data',
handler: function () {
grid.filters.clearFilters();
}
},{
text: 'Reconfigure Grid',
handler: function () {
grid.reconfigure(store, createColModel(6));
}
}
]);

var win = new Ext.Window({
title: 'Grid Filters Example',
height: 400,
width: 700,
layout: 'fit',
items: grid
}).show();

});

my jsp just has some println statements to test if there is anything in the filters arraylist


<%@page import="java.util.ArrayList"%>
<%@page import="org.json.simple.JSONValue"%>

<%
String start = request.getParameter("start");
String limit = request.getParameter("limit");
String sort = request.getParameter("sort");
String dir = request.getParameter("dir");

System.out.println("start= " + start);
System.out.println("limit= " + limit);
System.out.println("sort= "+sort);
System.out.println("dir= "+dir);

if (request.getParameter("q") != null && !request.getParameter("q").equals("")) {
String filter = (String) request.getParameter("q");
ArrayList filters = (ArrayList) JSONValue.parse(filter);
System.out.println("filter = " + filter);
System.out.println("filters= " + filters);
System.out.println("f= " + request.getParameter("f"));
System.out.println("f2= "+ request.getParameter("f2"));
System.out.println("==>" + request.getParameter("filter[0][data][type]"));
} else {
System.out.println("error getting parameter q");
}


%>


The output is as follows

start= 0
limit= 50
sort= null
dir= null
filter = []
filters= []
f=
f2=
==>null

Can anyone help me discover why my arraylist is empty even though I have set filters on the "company" and "size" columns?

Thank you for the help

nickweavers
27 Feb 2010, 5:47 AM
I ran into a similar confusing situation yesterday. The GridFilter plugin can be found within Ext 3.1.1 here:

/examples/ux/gridfilters/

Along with a very helpful example (look at all those includes!) found here:

/examples/grid-filtering/

And the "ux" branch of the Ext doc can be found here on the UX repository website:

http://extjs-ux.org/ext-docs/

Thanks Michael.

cnicolas
1 Mar 2010, 6:09 AM
Hi !
How it is possible to access directly to the filter menu, without show the standard hdmenu (with sorting and columns entries).
If I put enableHdMenu to false on my grid, the filter menu is then unreachable.

I wish to obtain something like this :
http://ccnicolas.free.fr/hdfilter.jpg
Thanks for any suggestion.

SunWuKung
3 Mar 2010, 1:34 AM
Hi,
Is there a way to send the filter request only when the filter is 'ready' - when the filter box is closed instead of updating with every change in the box?
Eg.
with list filter - when the user finished ticking and unticking,
with text filter - when the full search text is entered?

For larger datasets and remote filtering this would be better for me.
Thanks for the help.
SWK

sawan
8 Mar 2010, 8:16 PM
I grabbed it from the Ext 3 Demo:
http://extjs.com/deploy/dev/examples/grid-filtering/grid-filter-local.html

However, I found that sorting and filtering grids with a horizontal scroll bar was a) not preserving the horizontal scroll pos and b) was not displaying the column headings correctly until after the grid was scrolled or resized.

I don't know if this is by design, a bug or an incompatibility issue with the grid filter plug-in. So I put the following together until I can investigate further. It preserves the horizontal scroll pos onload (solves both my problems). I haven't found any problems with it yet...

Ext.ux.GridViewPreserveHScroll = Ext.extend(Ext.grid.GridView, {
onLoad: function() {
//overridden to preserve the horizontal scroll position
this.scroller.dom.scrollTop = 0;
}
});
Use an instance of this as the grid view in your grid...

clicksToEdit: 1,
view: new Ext.ux.GridViewPreserveHScroll(),
loadMask: true,
...
Tested in the browsers I have: IE6, IE8, FF3.5, Chrome 2, Safari 4 (Windows)

Doesn't work in Opera 9.64 for some reason - the headings display is not corrupted, but the horizontal scroll pos is not preserved.

hi,

i looked at your solution here http://www.extjs.com/forum/showthread.php?p=380127#post380127 and tried, but there is no change in the grid, in fact i get an error

a.init is not a function
[Break on this error] Ext.DomHelper=function(){var n=null;var ...(Ext.History,new Ext.util.Observable());

and the grid is not displayed

Can you pl help?

mcouillard
22 Mar 2010, 11:00 AM
Hi,
Is there a way to send the filter request only when the filter is 'ready' - when the filter box is closed instead of updating with every change in the box?
SWK


autoReload:false, local:false

mcouillard
24 Mar 2010, 10:24 AM
autoReload:false, local:false

Actually, setting the grid filter like that results in no action when you hit ENTER on a filter text field. State change events fire, but the store is never loaded with the chosen filter. I'm still working on a solution...

taronja
26 Mar 2010, 1:51 AM
Hi,

I still have a problem with the icon images at the filter menu. In FF or Chrome it renders perfect but in IE I can't see the menu images. There're some solutions to that issue in the older version but don't apply to the current.
Any idea?

Internet Explorer
http://www.agsoft.es/menu_ie.jpg

Firefox
http://www.agsoft.es/menu_ff.jpg

steffenk
26 Mar 2010, 2:15 AM
I like the filters. However it's hard to know if filters are applied, as you only can see it with open the column menu.
So i made a simple button in tbar to remove all filters, maybe you need the same or want enhance it:
in store listeners:

listeners: {
datachanged: function(store){
var hasFilters = false;
filters.filters.each(function (filter) {
if (filter.active) {
hasFilters = true;
}
});
if (hasFilters) {
this.doClearFilters.show();
} else {
this.doClearFilters.hide();
}
},
scope: this
},
and the button:

{
text: 'Clear all Filters',
ref: '../doClearFilters',
handler: function() {
filters.clearFilters();
},
scope: this,
hidden: true
},

mcouillard
26 Mar 2010, 4:37 AM
I like the filters. However it's hard to know if filters are applied, as you only can see it with open the column menu.

Applied filters have their column header changed to be bold and italic. Maybe you're missing a CSS file?
/ext-3.1.1/examples/ux/gridfilters/css/GridFilters.css
/ext-3.1.1/examples/ux/gridfilters/css/RangeMenu.css

Also, the standard Grid Filters package comes with a clearFilters() method. Like this:


oGrid.filters.clearFilters(); // disable column filters and reload store

steffenk
26 Mar 2010, 8:45 AM
i have the css included (of course) but i see no bold headers.
Also i think it's not that userfriendly. Think of having 3 filters active, to get back unfiltered you have to uncheck three different menus.

And in my example i already use the filters.clearFilters() ;)

mcouillard
26 Mar 2010, 9:51 AM
i have the css included (of course) but i see no bold headers.
Also i think it's not that userfriendly. Think of having 3 filters active, to get back unfiltered you have to uncheck three different menus.

And in my example i already use the filters.clearFilters() ;)

Strange, I can't think of any other reason why the column headers wouldn't get styled when a filter is applied. Ext 3.1.1, I assume. Have you overridden the default filterCls from "ux-filtered-column"?

Ah! I misunderstood the "ref" part of the example. Yes, I do agree that a single method to clear all column filters is very nice - I use it, too!

taronja
29 Mar 2010, 3:31 AM
Hi,

I still have a problem with the icon images at the filter menu. In FF or Chrome it renders perfect but in IE I can't see the menu images. There're some solutions to that issue in the older version but don't apply to the current.
Any idea?

Internet Explorer
http://www.agsoft.es/menu_ie.jpg

Firefox
http://www.agsoft.es/menu_ff.jpg
anybody helps?

asbestos girl
29 Mar 2010, 3:33 AM
Taronja, what version of Ext are you using? And do you have the latest code from the site? I do and i have no such problem (using 3.0.0).

taronja
29 Mar 2010, 3:37 AM
I also use 3.0.0 Thanks for the reply

asbestos girl
29 Mar 2010, 3:42 AM
Same as me then. Do you have the latest GridFilters code?
Does your GridFilters.css look like this?

/*!
* Ext JS Library 3.0+
* Copyright(c) 2006-2009 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
*/
/**
* GridFilters Styles
**/
/*
.x-grid3-hd-row .ux-filtered-column {
border-left: 1px solid #C7E3B4;
border-right: 1px solid #C7E3B4;
}

.x-grid3-hd-row .ux-filtered-column .x-grid3-hd-inner {
background-image: url(../images/header_bg.gif);
}

.ux-filtered-column .x-grid3-hd-btn {
background-image: url(../images/hd-btn.gif);
}
*/
.x-grid3-hd-row td.ux-filtered-column {
font-style: italic;
font-weight: bold;
}

.ux-filtered-column.sort-asc .x-grid3-sort-icon {
background-image: url(../images/sort_filtered_asc.gif) !important;
}

.ux-filtered-column.sort-desc .x-grid3-sort-icon {
background-image: url(../images/sort_filtered_desc.gif) !important;
}

.ux-gridfilter-text-icon {
background-image: url(../images/find.png) !important;
}

/* Temporary Patch for Bug ??? */
.x-menu-list-item-indent .x-menu-item-icon {
position: relative;
top: 3px;
left: 3px;
margin-right: 10px;
}
li.x-menu-list-item-indent {
padding-left:0px;
}
li.x-menu-list-item div {
display: inline;
}

taronja
29 Mar 2010, 3:48 AM
have you commented anything in this file?

Mine is the same but not commented. I'll copy yours and I'll try. Thank you!

asbestos girl
29 Mar 2010, 3:50 AM
Hi,
i have not commented it out, it came like this from the GridFilters example include files on extjs site. I suspect you dont have the latest version then. Try downloading the include files from the example and see if it will work then

taronja
29 Mar 2010, 4:01 AM
no luck abestos girl. I still can't see menu images. But in the css file you've posted there's no style to the < > and = images, that are the ones I can't see.
The column icon which notice that you have some filter applied is visible to me, also de image for sorting columns.
http://www.agsoft.es/menu_ieF.jpg

!!!!SOLVED!!!!! IT WAS THE CSS ORDER IN MY MAIN FILE. THANK YOU ALL FOR HELPING

mcouillard
29 Mar 2010, 4:03 AM
anybody helps?

Can you post the code of your grid and it's filter configuration? Could be as simple as an extra comma because something seems to be making IE think your column filters are disabled (that gray font color is my clue).

taronja
29 Mar 2010, 6:09 AM
filtering is working right. the grey colour is the mouseover the text menu effect. everything is going ok but the images on the menu. the < > and = symbols and the find icon for strings filtering doesn't appear in place with IE8 but it renders right with FF and Chrome, as seen in my first post

pmdarrow
5 Apr 2010, 6:51 AM
Hi all. Is there any way filter a column that's rendered using multiple data columns? For instance, I have a grid column with the header "Full Address" that uses a custom renderer ("addressRender") to combine Street, City, State/Province, Zip/Postal Code, and Country for each row. The column definition looks like this:


{ header: 'Full Address', dataIndex: 'Street', sortable: true, width: 168, renderer: this.addressRenderer } Notice that although the dataIndex is only 'Street', the render appends the data from the other columns using record.data.City, record.data.Country, etc. This poses a problem for the filtering plugin though because filters are defined by dataIndex and not column header.

The following filter definition will add filtering to the "Full Address" column but will only build queries against the Street column, not all of the other columns:

new Ext.ux.grid.GridFilters({
filters: [
{ dataIndex: 'Street', type: 'string' }
],
})
},Can anyone suggest a way to modify the grid filters plugin to work in this case?

SunWuKung
21 Apr 2010, 6:45 AM
Hi,
I would like to set the comparison type for string filter - currently its LIKE, but it could also be (at least) NOT LIKE, or REGEXP.
Ideally I would like to do it with a dropdown in the filter, but that looks difficult.
For most of my cases it would be enough if I could specify the comparison type sent to the server when I define the string filter.

Could someone tell me how to do this?
Many thanks.
SWK

mpawlowski
21 Apr 2010, 11:00 AM
I was having problems with this plugin when using object based record values while specifying a sort type and a renderer.



//Record Value
{
ordinal: 1,
text: 'foo'
}



//Store Field Decleration
{
name: 'columnDataIndex',
sortType: function(val){
return val.ordinal;
}
}



//Column Model decleration
{
header: 'Column Header',
dataIndex: 'columnDataIndex',
renderer: function(val){
return val.text
}
}



//ListFilter Decleration
{
type: 'list',
dataIndex: 'columnDataIndex',
options: ['Option1', 'Option2'],
labelField: 'text'
}

This caused problems when trying to create a list filter of enumerated values. I added some functionality to the list filter to have it account for this problem. If you specify a labelField when creating the filter in the list, then the list filter looks into the object of the record value and compares the filter option to the value of the labelField inside the record value object.



Ext.override(Ext.ux.grid.filter.ListFilter, {
validateRecord: function(record){
if (this.labelField) {
return this.getValue().indexOf(record.get(this.dataIndex)[this.labelField]) > -1;
}
else {
return this.getValue().indexOf(record.get(this.dataIndex)) > -1;
}
}
});

I saw someone using the labelField value in the filter, but I didn't see it in the decleration of ListFilter.js. If that is conflicting with something else its an easy change. This is just a small hack that might help someone else with a similar issue.

Also, if there is already a way to do this and I missed it, can someone enlighten me?

fulfowi
21 Apr 2010, 2:53 PM
I'm in the process of moving from ExtJs 2.0.1 to ExtJs 3.1.1. I got GridFilters to work in ExtJs 2.0.1, using examples absconded from ExtJs 2.2 with no problems. When I try to use the ExtJs 3.1.1 GridFilters examples (with ExtJs 3.1.1), every thing looks fine until I select a filter, which gives me the following trace in firebug:

this.proxy is undefined
anonymous("read", Object name=rs, Object params=Object, Object name=batch)ext-all-debug.js (line 33322)
anonymous(Object params=Object)ext-all-debug.js (line 33202)
anonymous(Object name=options)ext-all-debug.js (line 33571)
anonymous()GridFilters.js (line 507)
anonymous()ext-all-debug.js (line 1881)
[Break on this error] this.proxy.request(Ext.data....ack(action, rs, batch), this, options);\next-all-debug.js (line 33322)

At 507 in GridFilters.js it's doing a store.reload(). The grid just keeps trying to load.

Here's my complete code for the page:



//******************************************************************************
// $Id: logger.js@@/main/3 2009/10/07 14:27:17 dfulford $
//
// ABSTRACT: This javascript uses extjs to implement the logger window for the
// Algorithm Development Lab (ADL).
//
// $Log: /source/mission64t/tgirs_webapps/logger/resources/js/logger.js $
// /main/3 2009/10/07 14:27:17 dfulford
// TGIRS-921: See Jira Issue.
// /main/2 2009/03/30 10:50:20 dfulford
// TGIRS-565: See Jira Issue.
// /main/1 2009/03/25 15:52:12 dfulford
// TGIRS-551: See Jira Issue.
//
//******************************************************************************
var RCS_HEADER = "$Header: /source/mission64t/tgirs_webapps/logger/resources/js/logger.js@@/main/3 2009/10/07 14:27:17 dfulford $";
Ext.BLANK_IMAGE_URL = "images/default/s.gif";
var UI = {};
var DATA = {};
// "Included" modules.
var helpers;
if (!helpers || !helpers.Util)
{
throw new Error("helpers/Util.js has not been loaded.");
}
var copyToClipboard = helpers.Util.copyToClipboard;
//:MAINTENANCE: Change if changes in schema.
DATA.LOGGING_LEVELS = "LOGGING_LEVELS";
DATA.LOGGING_DEGREE = "LOGGING_DEGREE";
Ext.ux.grid.filter.StringFilter.prototype.icon = 'img/find.png';
function create()
{
var logMessages = [];
var logFieldDefinitions =
['systemTime', 'missionTime', 'source', 'type', 'level', 'message'];
DATA.logRecord = Ext.data.Record.create(logFieldDefinitions);
UI.logStore = new Ext.data.SimpleStore
({
fields: logFieldDefinitions,
data: logMessages
})
UI.loggingLevels =
opener.getEnumeration("dns:"+DATA.LOGGING_LEVELS);
UI.loggingDegree =
opener.getEnumeration("dns:"+DATA.LOGGING_DEGREE);
var sources = opener.getInstances();
sources.push('Executor');
var types = [];
for (var i=0; i<UI.loggingLevels.length; ++i)
{
types.push(UI.loggingLevels[i][0]);
}
var levels = [];
for (var i=0; i<UI.loggingDegree.length; ++i)
{
levels.push(UI.loggingDegree[i][0]);
}
var filters = new Ext.ux.grid.GridFilters
({
filters:
[{
type: 'string',
dataIndex: 'systemTime'
},{
type: 'string',
dataIndex: 'missionTime'
},{
type: 'list',
dataIndex: 'source',
options: sources
},{
type: 'list',
dataIndex: 'type',
options: types
},{
type: 'list',
dataIndex: 'level',
options: levels
},{
type: 'string',
dataIndex: 'message'
}]
});
UI.logDisplayGrid = new Ext.grid.GridPanel
({
store: UI.logStore,
columns:
[{
id: 'systemTime',
header: 'System Time',
width: 200,
sortable: true,
dataIndex: 'systemTime'
},{
id: 'missionTime',
header: 'Mission Time',
width: 200,
sortable: true,
dataIndex: 'missionTime'
},{
id: 'source',
header: 'Source',
width: 200,
sortable: true,
dataIndex: 'source'
},{
id: 'type',
header: 'Type',
width: 75,
sortable: true,
dataIndex: 'type'
},{
id: 'level',
header: 'Level',
width: 75,
sortable: true,
dataIndex: 'level'
},{
id: 'message',
header: 'Message',
width: 2000,
sortable: true,
dataIndex: 'message'
}],
autoScroll: true,
height: 1000,
plugins: filters,
region: 'center',
loadMask:true,
local: true
});
var viewport = new Ext.Viewport
({
layout: 'border',
items: [UI.logDisplayGrid]
})
}
function getLogMessages()
{
opener.showWait("Getting log messages ...", "Couldn't get log messages.");
Adl.getLogMessages(function(messages)
{
if (messages != null)
{
for (var i=0; i<messages.length; ++i)
{
var tokens = messages[i].split("\t");

if (tokens[0] != "System Time")
{
var log = new DATA.logRecord
({
systemTime: tokens[0],
missionTime: tokens[1],
source: tokens[2],
type: tokens[3],
level: tokens[4],
message: tokens[5]
});

UI.logStore.add(log);
}
}
}
opener.UI.waitBox.hide();
});
}
function startLog()
{
Adl.openLogPipe(opener.getRunOutDir()+'/logfile.tsv',
function(success)
{
if (success)
{
UI.logDisplayGrid.destroy();
create();
getLogMessages();
}
else
{
Ext.MessageBox.alert
("Warning",
"Couldn't open the log file.");
}
});
}
Ext.onReady(function()
{
create();
});



Any Ideas?

Condor
21 Apr 2010, 10:46 PM
Your store contains local data. That means you have to configure the GridFilters plugin with local:true.

SunWuKung
22 Apr 2010, 12:49 AM
Actually, setting the grid filter like that results in no action when you hit ENTER on a filter text field. State change events fire, but the store is never loaded with the chosen filter. I'm still working on a solution...

Thanks for the help ...
Now that I am doing regexp matching it is even more important for me to be able to do this because with the current setting there is a large number if incorrect requests while the pattern is not yet finished.

fulfowi
22 Apr 2010, 6:46 AM
Condor,

That did the trick!

KevinChristensen
29 Apr 2010, 8:38 AM
no luck abestos girl. I still can't see menu images. But in the css file you've posted there's no style to the < > and = images, that are the ones I can't see.
The column icon which notice that you have some filter applied is visible to me, also de image for sorting columns.
http://www.agsoft.es/menu_ieF.jpg

!!!!SOLVED!!!!! IT WAS THE CSS ORDER IN MY MAIN FILE. THANK YOU ALL FOR HELPING

We switched to use the /examples/ux/css/ux-all.css and /examples/ux/ux-all.js and found that the icons for gridfilter are looking in examples/ux/images but none of the images for gridfilter exist there releative to the ux-all.css.
They are all in examples/ux/gridfilters/images. We copied the images from ux/gridfilters/images to ux/images and now they appear in our web pages. I don't know what to recommend to address this problem but wanted to be sure someone was aware of it.

gleskinen
7 May 2010, 11:33 AM
I can't even get the filter menu to show. CreateMenu in GridFilters.js completes successfully but the filter menu item or separator are not in the column header menu when it drops down.

# eof
18 May 2010, 11:13 AM
Hi,

At first I would like to thank you for this great Ext-extension.

I just have one Problem with it. I can't insert certain characters into the text-filter. For example "&", "(" and "'" does not work with the german keyboard-layout. They just don't get inserted. Im shure there will be the same problems with the en-us keyboard layout, perhapst on other keys. It seems that the menu handle these keys as control-element and catch the insert-event.

You can see this behaviour in the online example: http://ccinct.com/lab/filter-grid/.

kind regards,

Arne

jamie.nicholson
23 May 2010, 5:46 PM
I have a number of re-usable stores loaded into Ext.StoreMgr and all have a storeId and are used in several places throughout an application. When I destroy the gridfilters it also takes the re-usable stores with it, which causes errors when other parts of the application try to start using the store.

I've implemented this override to fix the problem, you might consider adding it to the sauce as normally if you create a store without a storeId you won't re-reference it and can destroy/re-create at your pleasure.


Ext.override(Ext.ux.menu.ListMenu,{
destroy : function () {
if (this.store.storeId == undefined ) {
this.store.destroy();
}
Ext.ux.menu.ListMenu.superclass.destroy.call(this);
},
});

george4rotech
27 May 2010, 1:10 PM
Thanks for this awesome plugin, it plays nice with other plugins/extensions such as PagingStore and CheckColumn; see http://www.extjs.com/forum/showthread.php?71532-3.x-Ext.ux.data.PagingStore-v0.4&p=471722#post471722

When calling clearFilters however, although the data is reverted, the filter's input field retains the previously entered value. Please see attached screenshots I think they will demonstrate this better than my code could. Nevertheless for the sake of thoroughness below is the entire pertinent method from our code base, though the only pertinent lines are the last two.

Thanks in advance


this.userAccessLocationGrid.filters.clearFilters();
this.userAccessLocationGrid.store.loadData(locationsForGrid);

george4rotech
2 Jun 2010, 10:07 AM
When calling clearFilters however, although the data is reverted, the filter's input field retains the previously entered value.


The following override is a step toward addressing this issue. A simpler (more naive?) solution would have been to call "filter.setValue('')" inside clearFilter's original "this.filters.each(function (filter) {" loop, but setValue on most of the filters (at least the ones I read) also invoked the update event, which I don't think is desirable in this case.

Feedback appreciated.


(function() {
var originalClearGridFilters = Ext.ux.grid.GridFilters.prototype.clearFilters;

Ext.override(Ext.ux.grid.GridFilters, {
clearFilters: function() {
originalClearGridFilters.apply(this, arguments);

this.filters.each(function (filter) {
//prevent filter's update event from being called by setValue
var filterUpdateEvent = filter.events['update'];
delete filter.events['update'];

filter.setValue('');
filter.events['update'] = filterUpdateEvent; //revert
});
}
});
}());

msinn
10 Jun 2010, 8:34 AM
Hello,

would you please help me to get working the Filters on comboboxes with JsonStores?
I have here a test-case:

http://www.extjs.com/forum/showthread.php?101236-EditorGridPanel-Filters-don-t-apply-on-comboboxex-with-stores-Summary-Grouping-is (http://www.extjs.com/showthread.php?101236-EditorGridPanel-Filters-don-t-apply-on-comboboxex-with-stores-Summary-Grouping-is)

Thank you a lot, a lot
Marius

zeruyo
11 Jun 2010, 4:14 AM
The following override is a step toward addressing this issue. A simpler (more naive?) solution would have been to call "filter.setValue('')" inside clearFilter's original "this.filters.each(function (filter) {" loop, but setValue on most of the filters (at least the ones I read) also invoked the update event, which I don't think is desirable in this case.

Feedback appreciated.


(function() {
var originalClearGridFilters = Ext.ux.grid.GridFilters.prototype.clearFilters;

Ext.override(Ext.ux.grid.GridFilters, {
clearFilters: function() {
originalClearGridFilters.apply(this, arguments);

this.filters.each(function (filter) {
//prevent filter's update event from being called by setValue
var filterUpdateEvent = filter.events['update'];
delete filter.events['update'];

filter.setValue('');
filter.events['update'] = filterUpdateEvent; //revert
});
}
});
}());

Great solution. I tried to replace the update event 'hiding' with filter.suspendEvents() but it didn't work.
Thanks

Override
14 Jun 2010, 4:24 AM
Hi.
Can you help me please: how I can submit to server value of id, not text in ListFilter?

asbestos girl
17 Jun 2010, 12:55 AM
Override, can you please post the relevant snippets of your code?

SunWuKung
23 Jun 2010, 1:50 AM
Hi,
I have many columns in my grid (most of them normally hidden). When I want to check if a filter on them is on/off or I want to change the filter I first need to make them visible.

I was wondering if anybody has done some sort of filter manager eg. from a menu on the grid where the filters on the grid were listed and you could do the same functions then you do from the column header (switch on/off, change).
If yes could you please post the sample?

Many thanks.
SWK

asbestos girl
23 Jun 2010, 2:49 AM
Hi SWK,
I am not going to post an example as i dont have one and no time to write it, but it is definitely possible. Check out the documentation for the ux here: http://extjs-ux.org/docs/index.html, expand the menu tree there to GridFilters and Filter folders, and check out there available methods to get the data you need.

Override
23 Jun 2010, 7:48 AM
Hi.
Can you help me please: how I can submit to server value of id, not text in ListFilter?

Override, can you please post the relevant snippets of your code?
Actually, can't - already resolved by changing ListMenu.js, used by ListFilter.
By default, ListMenu creates internal store based on ListMenu.labelField property and value.id.

Shortly about changes: valueField property added to ListMenu class, and 'valueField'-related processing added to ListView store and events.

Solution is not tested for all cases and stores, however, it allows me to use JsonStore for ListFilter, like this:


new Ext.ux.grid.GridFilters(
{
{
type: 'list',
dataIndex: 'AdministrativeAreaID',
labelField: 'Name',
valueField: 'ID', //allow send value of this property to server
phpMode: true,
store: MyCache.GetStore("AdministrativeAreas") //returns new JsonStore with MemoryProxy
}
}

...and send following data to server during grid request:
filter[0][data][type] list
filter[0][data][value] 4,26
filter[0][field] AdministrativeAreaID

Changed ListMenu.js attached.

Thanks.

Reimius
29 Jun 2010, 12:28 PM
Hey guys... I ran into this huge issue (for us anyway) while using GridFilters that has an easy fix. Our business requirements have grids that require things like '%' and '$' to actually be in the store values (because the output is not only used for Extjs grids). This is easy enough to work around with data stores with the custom sorting method and grids, but this plugin did not work when a filter was set to 'numeric' and the field type in the store was set to 'string' and contained values like '25%' and such. I modified the 'validateRecord' function in the NumericFilter.js file to have the following code to make filtering work in the situation I described above. I would also appreciate people's comments if they see any potential problem with this fix or a better way to go about this, thanks.


validateRecord : function (record) {
var val = (record.get(this.dataIndex) + "").replace(/([^0-9\.])/g, ""),
values = this.getValue();
if (values.eq !== undefined && val != values.eq) {
return false;
}
if (values.lt !== undefined && val >= values.lt) {
return false;
}
if (values.gt !== undefined && val <= values.gt) {
return false;
}
return true;
}As you can see, I'm just using a regex expression to extract the numbers and/or decimal places out of the text.

ldonofrio
5 Aug 2010, 12:57 PM
I have a number of re-usable stores loaded into Ext.StoreMgr and all have a storeId and are used in several places throughout an application. When I destroy the gridfilters it also takes the re-usable stores with it, which causes errors when other parts of the application try to start using the store.

I've implemented this override to fix the problem, you might consider adding it to the sauce as normally if you create a store without a storeId you won't re-reference it and can destroy/re-create at your pleasure.


Ext.override(Ext.ux.menu.ListMenu,{
destroy : function () {
if (this.store.storeId == undefined ) {
this.store.destroy();
}
Ext.ux.menu.ListMenu.superclass.destroy.call(this);
},
});


true i'm usign autoDestroy flag to override


Ext.override(Ext.ux.menu.ListMenu, {
destroy: function() {
if (this.store && this.store.autoDestroy) {
this.store.destroy();
}
Ext.ux.menu.ListMenu.superclass.destroy.call(this);
}
});

lsaffre
5 Aug 2010, 1:14 PM
Thanks for this great plugin!

I got an error message `type.substr is not a function` because the type of my store's fields is not a string but one of Ext.data.Types. Seems that the version contained in ExtJS 3.2.1 doesn't like it.
I solved it by adding a line to the getFilterClass function:


getFilterClass : function (type) {
// map the supported Ext.data.Field type values into a supported filter
if (type.type) type = type.type; // <<<--- line added
switch(type) {
...


Luc

Fallen Zen
18 Aug 2010, 4:47 AM
I have a simple Filter on my grid. Question is, how can a list filter take the values directly from the grid without setting options? Column Producer holds the names of people. I cannot set all the possible options by hand. Thanks!



var viewerGridFilters = new Ext.ux.grid.GridFilters({
encode: false,
local: true,
filters: [{
type: 'list',
dataIndex: 'Producer',
options: []
},{
type: 'string',
dataIndex: 'Project'
},{
type: 'string',
dataIndex: 'Description'
},{
type: 'date',
dataIndex: 'StartDate'
},{
type: 'date',
dataIndex: 'EndDate'
}]
});

ldonofrio
18 Aug 2010, 5:28 AM
You have to create a Store with the distinct names of the Producers and link it with the list filter, see the store config option of the list filter.

jaquet
19 Aug 2010, 4:49 AM
Hi all,

I want to use the grid filter plugin, but I want the filter options to be in a separate Ext.panel, so that they are more visible than they are now, in the header. Does anybody know of some good examples on how to achieve this?

Timido
5 Sep 2010, 9:42 AM
Hello,

I downloaded ExtJS version 3.2.1, but cannot find this plugin within that distribution, nor the documentation (there's no "ux" node in the doc tree).

I thought this plugin was included into version 3.x of ExtJS... am I wrong somewhere or do I need to install something more?

Thank you!

Condor
5 Sep 2010, 10:50 AM
User extensions can be found in the examples/ux directory of the SDK.

Ext 3.2 didn't have ux documentation yet, but you can check the preliminary Ext 3.3 ux docs (http://dev.sencha.com/deploy/ext-3.3-beta2-7080/examples/ux/docs/?class=Ext.ux.grid.GridFilters).

Timido
11 Sep 2010, 12:33 PM
Thanks Condor :)


Also, as for this:

Hi all,

I want to use the grid filter plugin, but I want the filter options to be in a separate Ext.panel, so that they are more visible than they are now, in the header. Does anybody know of some good examples on how to achieve this?

I am also interested in such a feature or maybe having the filter in a row... any clues?

Condor
12 Sep 2010, 12:55 AM
1. Create a formpanel with the fields you want to use for filtering and a 'Search' button.
2. Put both the formpanel and the grid in a container with border or vbox layout.
3. In the search button handler either filter the store (if all records are already loaded) or load the store with the field values as parameters.

Timido
13 Sep 2010, 9:51 AM
Sorry about this, having some troubles with actually installing the extension, or at least not really sure about it.

Does it suffice to move ALL the content of ext-3.2.1\examples\ux\gridfilters (So the main GridFilters.js plus the other subdirectories) at my web site location and including GridFilters.js from within the HTML web page?

(looks like it can find the class!)

Thanks again for all!

Oliver Specht
18 Sep 2010, 8:26 AM
Hi,
I have a problem with the icons in the numeric filter.

The icons are all in the first row where the input fields are positioned correctly.

Just look at the screenshot and you will know what I mean.

22464

Can anyone help me out?

Thanks,
Oliver

pouniok
20 Sep 2010, 2:29 AM
Hi,


While upgrading from Ext 3.1.1 to Ext 3.2.1, we faced a problem with the GridFilters plugin.

To explain, we have a FormPanel with some fields, and when we type in those fields, it activates the columns filters. This works perfectly, it's just a way to show the filters instead of having them hidden in the columns menus.

But then, we have a report engine, to print the grid data. The report engine is using the parameters of the grid store to get the same results, and in the Ext 3.1.1 the GridFilters plugin was well saved in the store.lastOptions of the grid.

Since Ext 3.2.1, the lastOptions object did not contain any information about the sent filters.

Someone has a clue how I could fix this ? The plugin didn't seem to have changed, so maybe the store has a different way to handle requests, but I didn't find anything while looking for it.


Thank you,
Pouniok.

jimm
28 Sep 2010, 2:11 PM
Wonderful work. Using Ext 3 and have a question about clearing the checked filter data items. Not entirely clear how to do this. Our app has a "Clear Filter Data" button and clearFilters() unchecks the parent "Filter" in the menu pulldown, but not the data items in the filter list. We want to uncheck those. Suggestions? Thanks very much.

asbestos girl
29 Sep 2010, 1:40 AM
pouniok,
did you upgrade your GridFilters files too, or just base ext libraries?

seg
12 Oct 2010, 12:43 AM
Don't know if this is a known issue, but when upgrading from 3.1.1 to 3.2.2 the booleanfilter is not working when using dynamic filter loading. It is because the property this.store.fields.get(dI).type.type is returning 'bool' instead of the expected 'boolean' value. You can change the getFilterClass to make it work again:

getFilterClass : function (type) {
// map the supported Ext.data.Field type values into a supported filter
switch(type) {
case 'auto':
type = 'string';
break;
case 'int':
case 'float':
type = 'numeric';
break;
case 'bool':
type = 'boolean';
break;
}
return Ext.ux.grid.filter[type.substr(0, 1).toUpperCase() + type.substr(1) + 'Filter'];
}

webtime
24 Oct 2010, 2:06 PM
Anyone can help me in adding this plugin to a dinamic grid (configured via json)???
Thanks to all for answer...

dizor
26 Oct 2010, 2:31 AM
In my case keyboard arrows doesn't work in textfield (string filter) - the same in examples. Any solutions?

webtime
4 Nov 2010, 3:21 AM
Anyone have some sample for configure filter via json (column model for dinamic grid) and not via filters var???
Thanks for answer..

ExTriqui
4 Nov 2010, 4:07 AM
You mean this?:


columns: [
{dataIndex: "customer", header: "Customer", width: 2, filter: {type: "string"}},
{dataIndex: "credit", header: "Credit limit", width: 1, filter: {type: "float"}}
]

msinn
4 Nov 2010, 4:11 AM
maybe that could help you:

ext/examples/ux/gridfilters/GridFilters.js line 75
ext/examples/grid-filter-local.js line line 87
http://dev.sencha.com/deploy/dev/examples/docs/?class=Ext.ux.grid.GridFilters

webtime
4 Nov 2010, 4:31 AM
You mean this?:


columns: [
{dataIndex: "customer", header: "Customer", width: 2, filter: {type: "string"}},
{dataIndex: "credit", header: "Credit limit", width: 1, filter: {type: "float"}}
]



Yes, but nothing appear in header menu...
Have you some example of grid definition with this type of configuration (column model via json)??
ThankS!!!!!!!

msinn
4 Nov 2010, 4:51 AM
Yes, but nothing appear in header menu...
Have you some example of grid definition with this type of configuration (column model via json)??
ThankS!!!!!!!



// use a factory method to reduce code while demonstrating
// that the GridFilter plugin may be configured with or without
// the filter types (the filters may be specified on the column model
var createColModel = function (finish, start) {

var columns = [{
dataIndex: 'id',
header: 'Id',
// instead of specifying filter config just specify filterable=true
// to use store's field's type property (if type property not
// explicitly specified in store config it will be 'auto' which
// GridFilters will assume to be 'StringFilter'
filterable: true
//,filter: {type: 'numeric'}
}, {
dataIndex: 'company',
header: 'Company',
id: 'company',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'price',
header: 'Price',
filter: {
//type: 'numeric' // specify type here or in store fields config
}
}, {
dataIndex: 'size',
header: 'Size',
filter: {
type: 'list',
options: ['small', 'medium', 'large', 'extra large']
//,phpMode: true
}
}, {
dataIndex: 'date',
header: 'Date',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
filter: {
//type: 'date' // specify type here or in store fields config
}
}, {
dataIndex: 'visible',
header: 'Visible',
filter: {
//type: 'boolean' // specify type here or in store fields config
}
}];

return new Ext.grid.ColumnModel({
columns: columns.slice(start || 0, finish),
defaults: {
sortable: true
}
});
};

webtime
4 Nov 2010, 5:02 AM
// use a factory method to reduce code while demonstrating
// that the GridFilter plugin may be configured with or without
// the filter types (the filters may be specified on the column model
var createColModel = function (finish, start) {

var columns = [{
dataIndex: 'id',
header: 'Id',
// instead of specifying filter config just specify filterable=true
// to use store's field's type property (if type property not
// explicitly specified in store config it will be 'auto' which
// GridFilters will assume to be 'StringFilter'
filterable: true
//,filter: {type: 'numeric'}
}, {
dataIndex: 'company',
header: 'Company',
id: 'company',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'price',
header: 'Price',
filter: {
//type: 'numeric' // specify type here or in store fields config
}
}, {
dataIndex: 'size',
header: 'Size',
filter: {
type: 'list',
options: ['small', 'medium', 'large', 'extra large']
//,phpMode: true
}
}, {
dataIndex: 'date',
header: 'Date',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
filter: {
//type: 'date' // specify type here or in store fields config
}
}, {
dataIndex: 'visible',
header: 'Visible',
filter: {
//type: 'boolean' // specify type here or in store fields config
}
}];

return new Ext.grid.ColumnModel({
columns: columns.slice(start || 0, finish),
defaults: {
sortable: true
}
});
};


Thanks, but i've read this....
I've configured my grid with metadata (dynamic columns) and i've specified the "filter" in json array from my servlet.
..... but..... nothing appears, i can't see any filter created on the grid.

ExTriqui
4 Nov 2010, 5:41 AM
The filter is a submenu in the column menu! you know that, right? You should make sure you have included all the javascript and css files required to get it working.
Add all of them, just in case:


<link rel="stylesheet" href="examples/ux/gridfilters/css/GridFilters.css" type="text/css" media="all" />
<link rel="stylesheet" href="examples/ux/gridfilters/css/RangeManu.css" type="text/css" media="all" />

<script type="text/javascript" src="examples/ux/gridfilters/menu/RangeMenu.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/menu/ListMenu.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/GridFilters.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/Filter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/StringFilter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/DateFilter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/ListFilter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/NumericFilter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/BooleanFilter.js"></script>

webtime
4 Nov 2010, 5:53 AM
The filter is a submenu in the column menu! you know that, right? You should make sure you have included all the javascript and css files required to get it working.
Add all of them, just in case:


<link rel="stylesheet" href="examples/ux/gridfilters/css/GridFilters.css" type="text/css" media="all" />
<link rel="stylesheet" href="examples/ux/gridfilters/css/RangeManu.css" type="text/css" media="all" />

<script type="text/javascript" src="examples/ux/gridfilters/menu/RangeMenu.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/menu/ListMenu.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/GridFilters.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/Filter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/StringFilter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/DateFilter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/ListFilter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/NumericFilter.js"></script>
<script type="text/javascript" src="examples/ux/gridfilters/filter/BooleanFilter.js"></script>



Ok, i do that!!!
But the plugins is ok only if a declare a "var filters = new Ext.ux eccc."
if i not declare this var, i don't see anything and none errors appear.

msinn
4 Nov 2010, 6:16 AM
Ok, i do that!!!
But the plugins is ok only if a declare a "var filters = new Ext.ux eccc."
if i not declare this var, i don't see anything and none errors appear.

I think you need an instance of that class to configure it (directly or in the column model) and for the grid's config option:



plugins:[yourVarFilter]


an for the PagingToolbar as well

webtime
4 Nov 2010, 6:33 AM
I think you need an instance of that class to configure it (directly or in the column model) and for the grid's config option:



plugins:[yourVarFilter]


an for the PagingToolbar as well


i try, this evening.....
..therefore... i must include : plugins:[new Ext.ux.GridFilter()] in my json generated from servlet for configuring grid
and plugins:[new Ext.ux.GridFilter()] in paging toolbar, it's right???

ExTriqui
4 Nov 2010, 7:18 AM
Well, I think the toolbar is a different thing.
But now that I read the last three post, it's clear that you misunderstood something.
You have to add the grid filters plugin to your grid plugins array in order to use filters at all:


var filters = new Ext.ux.GridFilter();

var grid = new grid {...
...
plugins: [filters]
}


Then you have to ways of configuring how they will work.
1. You can define your config options in the gridfilter directly.
2. You can and your filtering options in the column definitions as explained above, thus saving some duplicated code.

webtime
4 Nov 2010, 7:26 AM
Well, I think the toolbar is a different thing.
But now that I read the last three post, it's clear that you misunderstood something.
You have to add the grid filters plugin to your grid plugins array in order to use filters at all:


var filters = new Ext.ux.GridFilter();

var grid = new grid {...
...
plugins: [filters]
}


Then you have to ways of configuring how they will work.
1. You can define your config options in the gridfilter directly.
2. You can and your filtering options in the column definitions as explained above, thus saving some duplicated code.

Thanks, now i understand.....correctly....
I try ASAP....
Can i contact you via PM if i had some problem??
(Sorry for my english!!!!)

msinn
4 Nov 2010, 8:14 AM
i try, this evening.....
..therefore... i must include : plugins:[new Ext.ux.GridFilter()] in my json generated from servlet for configuring grid
and plugins:[new Ext.ux.GridFilter()] in paging toolbar, it's right???

I don't think that is the right way:


var grid = new Ext.grid.GridPanel ({

...

plugins: [new Ext.ux.grid.GridFilters()],

...

)};
because the class Component initializes the plugin in this way(take a look to ext-all-debug.js line 10648):



initPlugin : function(p){
10649 if(p.ptype && !Ext.isFunction(p.init)){
10650 p = Ext.ComponentMgr.createPlugin(p);
10651 }else if(Ext.isString(p)){
10652 p = Ext.ComponentMgr.createPlugin({
10653 ptype: p
10654 });
10655 }
10656 p.init(this);
10657 return p;
10658 },
But this is a good question, maybe somebody of the experienced developers would like to answer it :)

webtime
4 Nov 2010, 1:28 PM
This is my code json for automatic configuration of the grid:


{"columns": [{"filterable":true,"dataIndex":"objectUser","header":"Utilizzatore","filter":{"type":"string","dataIndex":"objectUser"},"decorated":false},{"filterable":true,"dataIndex":"objectCode","header":"Oggetto","filter":{"type":"string","dataIndex":"objectCode"},"decorated":false},{"filterable":true,"dataIndex":"userID","header":"Utente\/Oggetto","filter":{"type":"string","dataIndex":"userID"},"decorated":false},{"filterable":true,"dataIndex":"gridCode","header":"Codice Lista","filter":{"type":"string","dataIndex":"gridCode"},"decorated":false},{"filterable":true,"dataIndex":"applicationArea","header":"Area Applicativa","filter":{"type":"string","dataIndex":"applicationArea"},"decorated":false},{"dataIndex":"mKey","header":"mKey","hidden":true}],"filters":[{"type":"string","dataIndex":"objectUser"},{"type":"string","dataIndex":"objectCode"},{"type":"string","dataIndex":"userID"},{"type":"string","dataIndex":"gridCode"},{"type":"string","dataIndex":"applicationArea"}]}

thi is my grid code:


var filters = new Ext.ux.grid.GridFilters({});

xgrid = new Ext.ux.GridExtension({
layout:'fit'
,border:false
,stateful:false
,store:store
,loadMask: true
,stripeRows: true
,plugins: [filters]
,columns:[]
,viewConfig:{onDataChange: function(){
var columns = [];
columns.push(smodel);
for (var i = 0; i < this.ds.reader.jsonData.totcol; i++) {
eval("this.ds.reader.jsonData.columns[i].renderer = "+this.ds.reader.jsonData.columns[i].renderer);
columns.push(this.ds.reader.jsonData.columns[i]);
}
this.cm.setConfig(columns);
this.syncFocusEl(0);

},
forceFit:true,
emptyText: 'No records.'}
,tbar: tb
,sm : smodel
,bbar : new Ext.PagingToolbar({
store: store
,displayInfo:true
,pageSize:Prowperpage
})
});
xgrid.store.load({params:{start:0,limit:Prowperpage}});

.... i dont' see any filter menu......
anyone can help me???
Thanks!!!!!!!!!!!!!!!!

ExTriqui
5 Nov 2010, 2:09 AM
I'm not sure, but your column model definition has a lot of values which are duplicated.
If you define filtering options in your column model you don't need to add the filters definition again.
Try this, just in case:


{"columns": [
{"dataIndex":"objectUser","header":"Utilizzatore","filter":{"type":"string"},"decorated":false},
{"dataIndex":"objectCode","header":"Oggetto","filter":{"type":"string"},"decorated":false},
{"dataIndex":"userID","header":"Utente\/Oggetto","filter":{"type":"string"},"decorated":false},
{"dataIndex":"gridCode","header":"Codice Lista","filter":{"type":"string"},"decorated":false},
{"dataIndex":"applicationArea","header":"Area Applicativa","filter":{"type":"string"},"decorated":false},
{"dataIndex":"mKey","header":"mKey","hidden":true}
]}

Or this:


{"columns": [
{"dataIndex":"objectUser","header":"Utilizzatore","filterable":true,"decorated":false},
{"dataIndex":"objectCode","header":"Oggetto","filterable":true,"decorated":false},
{"dataIndex":"userID","header":"Utente\/Oggetto","filterable":true,"decorated":false},
{"dataIndex":"gridCode","header":"Codice Lista","filterable":true,"decorated":false},
{"dataIndex":"applicationArea","header":"Area Applicativa","filterable":true,"decorated":false},
{"dataIndex":"mKey","header":"mKey","hidden":true}
]}

webtime
5 Nov 2010, 10:57 AM
I tried without success.......

I copy my complete json:


{"metaData":
{"totalProperty": "total",
"root": "records",
"fields": [
{"name":"objectUser","mapping":"Utilizzatore","type":"string"}, {"name":"objectCode","mapping":"Oggetto","type":"string"},
{"name":"userID","mapping":"Utente\/Oggetto","type":"string"},
{"name":"gridCode","mapping":"Codice Lista","type":"string"},
{"name":"applicationArea","mapping":"Area Applicativa","type":"string"},
{"name":"mKey","mapping":"mKey","type":"string"}
]},
"success": true,
"total": 129,
"records": [----cancelled----],
"totcol":5,
"columns": [
{"dataIndex":"objectUser","header":"Utilizzatore","filter":{"type":"string","dataIndex":"objectUser"},"decorated":false},{"dataIndex":"objectCode","header":"Oggetto","filter":{"type":"string","dataIndex":"objectCode"},"decorated":false},{"dataIndex":"userID","header":"Utente\/Oggetto","filter":{"type":"string","dataIndex":"userID"},"decorated":false},
{"dataIndex":"gridCode","header":"Codice Lista","filter":{"type":"string","dataIndex":"gridCode"},"decorated":false},{"dataIndex":"applicationArea","header":"Area Applicativa","filter":{"type":"string","dataIndex":"applicationArea"},"decorated":false},{"dataIndex":"mKey","header":"mKey","hidden":true}]} ..... and the grid code:


var filters = new Ext.ux.grid.GridFilters({});

xgrid = new Ext.ux.GridExtension({
layout:'fit'
,border:false
,stateful:false
,store:store
,loadMask: true
,stripeRows: true
,plugins: [filters]
,columns:[]
,viewConfig:{onDataChange: function(){
var columns = [];
columns.push(smodel);
for (var i = 0; i < this.ds.reader.jsonData.totcol; i++) {
eval("this.ds.reader.jsonData.columns[i].renderer = "+this.ds.reader.jsonData.columns[i].renderer);
columns.push(this.ds.reader.jsonData.columns[i]);
}
this.cm.setConfig(columns);
this.syncFocusEl(0);

},
forceFit:true,
emptyText: 'No records.'}
,tbar: tb
,sm : smodel
,bbar : new Ext.PagingToolbar({
store: store
,displayInfo:true
,pageSize:Prowperpage
})
});
xgrid.store.load({params:{start:0,limit:Prowperpage}});I modified json for duplication... but ... nothing appear..
Anyone help me please!!!!!!!!!

Christiand
22 Nov 2010, 8:24 AM
I have somehow the same problem as webtime. My store loads 26 fields but it displays only 2 fixed + 8 variables. On a button press, the column model are changed using the setConfig method from the ColumnModel class. Here's bits from my code



activeType = null,
/**
* Change columns view between counter, service and totals fields
*/
chgColCfg: function(b, e){
this.activeType = b.activeType;
var newColSettings = this.getColSettings()
this.getColumnModel().setConfig(newColSettings, false)
},

getGridStore: function(){

var CustStore = ({
xtype: 'jsonstore',
autoLoad: true,
url: '/customer/getcustyearrec/',
root: 'data',
fields: [
{name:'DIV', type: 'string'},
{name:'YEAR', type: 'int'},

// Counter fields
{name:'CPNUM', type: 'int'},
{name:'CPQTY', type: 'float'},
{name:'CSALESAMT',type: 'float'},
{name:'CSALESDISC',type: 'float'},
{name:'CSALESNET',type: 'float'},
{name:'CCOST',type: 'float'},
{name:'CPMARG',type: 'float'},
{name:'CPMARGPE', type: 'float'},

// Service fields
{name:'SPNUM', type: 'int'},
{name:'SPQTY', type: 'float'},
{name:'SSALESAMT',type: 'float'},
{name:'SSALESDISC',type: 'float'},
{name:'SSALESNET',type: 'float'},
{name:'SCOST',type: 'float'},
{name:'SPMARG',type: 'float'},
{name:'SPMARGPE', type: 'float'},

//total fields
{name:'TPNUM', type: 'int'},
{name:'TPQTY', type: 'float'},
{name:'TSALESAMT',type: 'float'},
{name:'TSALESDISC',type: 'float'},
{name:'TSALESNET',type: 'float'},
{name:'TCOST',type: 'float'},
{name:'TPMARG',type: 'float'},
{name:'TPMARGPE', type: 'float'},
{name:'is_leaf', type: 'bool', defaultValue: false},
],
scope: this
});
return CustStore
},

getColSettings: function() {

var colType = this.getColStoreIndex() //returns C, S or T
var vpCols = [
{id: 'Div', header: this.colHeadDivision, dataIndex: 'DIV'},
{id: 'Year', header: this.colHeadYear, renderer: this.change, dataIndex: 'YEAR', align: 'right', filterable: true},
{id: 'Num', header: this.colHeadNum, renderer: this.change, dataIndex: colType+'PNUM', align: 'right', filterable: true},
{id: 'Qty', header: this.colHeadQty, renderer: this.change, dataIndex: colType+'PQTY', align: 'right', filterable: true},
{id: 'Amt', header: this.colHeadAmt, renderer: this.change, dataIndex: colType+'SALESAMT', align: 'right', filterable: true},
{id: 'Disc', header: this.colHeadDsc, renderer: this.change, dataIndex: colType+'SALESDISC', align: 'right', filterable: true},
{id: 'Net', header: this.colHeadNet, renderer: this.change, dataIndex: colType+'SALESNET', align: 'right', filterable: true},
{id: 'Cost', header: this.colHeadCost, renderer: this.change, dataIndex: colType+'COST', align: 'right', filterable: true},
{id: 'Marg', header: this.colHeadPMar, renderer: this.change, dataIndex: colType+'PMARG', align: 'right', filterable: true},
{id: 'MargPe', header: this.colHeadPMarPe, renderer: this.pctChange, dataIndex: colType+'PMARGPE', align: 'right', filterable: true},
];

return vpCols
},

getColsModel: function(){

var vpCols = this.getColSettings();
var vPcm = new Ext.grid.ColumnModel({
defaults: {
sortable: true,
editable: false
},
columns: vpCols
})
return vPcm;
},

initComponent : function() {

var filters = new Ext.ux.grid.GridFilters({
local: 'local',
updateBuffer: '250'
});

Ext.apply(this, {
height: 180,
store: this.getGridStore(),
stripeRows: true,
colModel: this.getColsModel(),
viewConfig: {
},
sm: new Ext.grid.RowSelectionModel({
singleSelect:true
}),
plugins: [filters],
frame: true
}
);
}


On first load, the "counter field" are displayed. All the filter options are available from the menu. This works perfectly. When a user click a button, the chgColCfg() method is called (a new activeType is set). The grid's refresh properly, however I loose all the grid filters BUT the one from the "year" column.

I probably need to re-initialize the pluggins but I am not sure how.

leowyatt
23 Nov 2010, 3:22 AM
Firstly,

Thanks for a great feature the filter works really well though I haven't implemented any remove filtering yet. I'm having some trouble with the icons for the filtering. I've included;


<script type="text/javascript" src="ux/menu/EditableItem.js"></script>
<script type="text/javascript" src="ux/menu/RangeMenu.js"></script>
<script type="text/javascript" src="ux/grid/GridFilters.js"></script>
<script type="text/javascript" src="ux/grid/filter/Filter.js"></script>
<script type="text/javascript" src="ux/grid/filter/StringFilter.js"></script>
<script type="text/javascript" src="ux/grid/filter/DateFilter.js"></script>
<script type="text/javascript" src="ux/grid/filter/ListFilter.js"></script>
<script type="text/javascript" src="ux/grid/filter/NumericFilter.js"></script>
<script type="text/javascript" src="ux/grid/filter/BooleanFilter.js"></script>
<link rel="stylesheet" type="text/css" href="RangeMenu.css" />
<link rel="stylesheet" type="text/css" href="GridFilters.css" />I've modified the css to locate the icon files however when I try to filter on a string I get this;

23474

With the numerical filtering I get this;

23473

I'll be honest I'm really struggling to understand why this has happened. I think it's something blindingly obvious I'm just missing.

EDIT: I've fixed the missing icons, that was a spelling mistake but I've still got them all doubled up.

Condor
23 Nov 2010, 3:55 AM
Can you poke it with Firebug to see why the individual filter menu items are too high?

leowyatt
23 Nov 2010, 3:59 AM
Can you poke it with Firebug to see why the individual filter menu items are too high?

I'm not sure what you mean by too high, they are actually duplicated and occur twice.

23475

Condor
23 Nov 2010, 4:10 AM
OK, now look at the <img> tag and tell use why it is higher than 16px.

leowyatt
23 Nov 2010, 4:34 AM
OK, now look at the <img> tag and tell use why it is higher than 16px.

Is it because the 2nd image has margins?

Condor
23 Nov 2010, 4:50 AM
No, that first <img> shouldn't even be there!

Also, that include list looks wrong. It includes css from Ext 3 and javascript from Ext 2. Which Ext version are you actually using?

leowyatt
23 Nov 2010, 5:13 AM
No, that first <img> shouldn't even be there!

Also, that include list looks wrong. It includes css from Ext 3 and javascript from Ext 2. Which Ext version are you actually using?

The ext version I'm using is 3.3.0

Condor
23 Nov 2010, 5:18 AM
In that case you should be using:

<link rel="stylesheet" type="text/css" href="ext/examples/ux/gridfilters/css/GridFilters.css" />
<link rel="stylesheet" type="text/css" href="ext/examples/ux/gridfilters/css/RangeMenu.css" />
<script type="text/javascript" src="ext/examples/ux/gridfilters/menu/RangeMenu.js"></script>
<script type="text/javascript" src="ext/examples/ux/gridfilters/menu/ListMenu.js"></script>
<script type="text/javascript" src="ext/examples/ux/gridfilters/GridFilters.js"></script>
<script type="text/javascript" src="ext/examples/ux/gridfilters/filter/Filter.js"></script>
<script type="text/javascript" src="ext/examples/ux/gridfilters/filter/StringFilter.js"></script>
<script type="text/javascript" src="ext/examples/ux/gridfilters/filter/DateFilter.js"></script>
<script type="text/javascript" src="ext/examples/ux/gridfilters/filter/ListFilter.js"></script>
<script type="text/javascript" src="ext/examples/ux/gridfilters/filter/NumericFilter.js"></script>
<script type="text/javascript" src="ext/examples/ux/gridfilters/filter/BooleanFilter.js"></script>

leowyatt
23 Nov 2010, 5:41 AM
Cheers Condor it didn't even click this was all in the examples directory. I'd added the file manually but seems things weren't right as once I copied your code over and put in the correct paths it worked perfectly.

Fabyo
23 Nov 2010, 7:41 AM
how do I clear the fields of search?
using clearFilters(), it only cleans the headlines, but what was typed in the search still continues in the fields, how do I clear all fields of search?

23484

thanks

msinn
23 Nov 2010, 11:47 AM
how do I clear the fields of search?
using clearFilters(), it only cleans the headlines, but what was typed in the search still continues in the fields, how do I clear all fields of search?
thanks

Hi, try this:




Ext.override(Ext.ux.grid.GridFilters, {
clearFilters : function () {
this.filters.each(function (filter) {
filter.setValue('');
//or filter.setValue(null);
filter.setActive(false);
});
}
});

Fabyo
23 Nov 2010, 11:53 AM
Thank you

pouniok
25 Nov 2010, 2:08 AM
Hi,

I've found a change Between Ext 3.1.1 GridFilters.js and Ext 3.3.0 GridFilters.js :

In function addFilters, line 575 has changed


from : filter.type = filter.type || this.store.fields.get(dI).type;
to : filter.type = filter.type || this.store.fields.get(dI).type.type;


And I was wondering if it was volumtary ?

filippo.ferrari
26 Nov 2010, 1:10 AM
A question related to grid filtering: how to configure a remote data source with a store for list filter?

I've not understand this:

"If the data for the list is remote, use the {@link #store} config instead."

msinn
26 Nov 2010, 1:24 AM
A question related to grid filtering: how to configure a remote data source with a store for list filter?

I've not understand this:

"If the data for the list is remote, use the {@link #store} config instead."

Hi,

first you have to configure a store for your filter:




var storeFilter = new Ext.data.JsonStore({
storeId: 'yourStoreId',
autoLoad: false,//or as you need it
proxy: new Ext.data.HttpProxy({
url: 'database.php'
}),
root: 'rows',
fields: [ 'id', 'text'] //it is important to have the fields named as 'id' and 'text'
});

Then




var gridFilter= new Ext.ux.grid.GridFilters({
menuFilterText: 'Filter',
filters:[{type: 'string', dataIndex: 'NAME'}
,{type: 'list', dataIndex:'STATE', store:storeFilter, phpMode:true} //your case
]});

In your grid load script you need to have something like this(here for PHP):




<?php
$where = " 0 = 0 ";
if (is_array($filter)) {
for ($i=0;$i<count($filter);$i++){
switch($filter[$i]['data']['type']){
case 'string' : $qs .= " AND ".$filter[$i]['field']." LIKE '%".$filter[$i]['data']['value']."%'"; break;
case 'list' :
if (strstr($filter[$i]['data']['value'],',')){
$fi = explode(',',$filter[$i]['data']['value']);
for ($q=0;$q<count($fi);$q++){
$fi[$q] = "'".$fi[$q]."'";
}
$filter[$i]['data']['value'] = implode(',',$fi);
$qs .= " AND ".$filter[$i]['field']." IN (".$filter[$i]['data']['value'].")";
}else{
$qs .= " AND ".$filter[$i]['field']." = '".$filter[$i]['data']['value']."'";
}
Break;
case 'boolean' : $qs .= " AND ".$filter[$i]['field']." = ".($filter[$i]['data']['value']); break;
case 'numeric' :
switch ($filter[$i]['data']['comparison']) {
case 'ne' : $qs .= " AND ".$filter[$i]['field']." != ".$filter[$i]['data']['value']; break;
case 'eq' : $qs .= " AND ".$filter[$i]['field']." = ".$filter[$i]['data']['value']; break;
case 'lt' : $qs .= " AND ".$filter[$i]['field']." < ".$filter[$i]['data']['value']; break;
case 'gt' : $qs .= " AND ".$filter[$i]['field']." > ".$filter[$i]['data']['value']; break;
}
break;
case 'date' :
switch ($filter[$i]['data']['comparison']) {
case 'ne' : $qs .= " AND ".$filter[$i]['field']." != '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; break;
case 'eq' : $qs .= " AND ".$filter[$i]['field']." = '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; break;
case 'lt' : $qs .= " AND ".$filter[$i]['field']." < '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; break;
case 'gt' : $qs .= " AND ".$filter[$i]['field']." > '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; break;
}
Break;
}
}
$where .= $qs;
}

filippo.ferrari
26 Nov 2010, 1:44 AM
Ok, great. I'll test it.

One note, this: labelField: 'name' override the name 'text' for display name of data in my store, it's true? (I've a store already and I want to reuse it)

msinn
26 Nov 2010, 1:55 AM
Ok, great. I'll test it.

One note, this: labelField: 'name' override the name 'text' for display name of data in my store, it's true? (I've a store already and I want to reuse it)

STATE ist the dataIndex config option of your Column which is bound to your field name of the store record (grid store), so the filter is just bound to it too. Your filter send to your grid load script STATE. Play a little bit with firebug and you'll see exactly how the filter parameters are sent.

Fabyo
26 Nov 2010, 2:08 AM
How do I create a listeners for when they use the search button to "clearFilters" stand on, that do not have any value in the search fields the button is disabled

2354623547

+-

listeners: {
change: function() {
if (condicao) {
clearFiltersButton.enable();
} else {
clearFiltersButton.disable();
}
}
}

?

thanks

filippo.ferrari
26 Nov 2010, 3:30 AM
STATE ist the dataIndex config option of your Column which is bound to your field name of the store record (grid store), so the filter is just bound to it too. Your filter send to your grid load script STATE. Play a little bit with firebug and you'll see exactly how the filter parameters are sent.

Ok, client-side works as aspected, and params are sent aspected too, now I'm focused on server side!! My trouble was to link the store correctly.

An extra question, anyone has developed a filter using ExtComboBox? (using a store to get remote data)....

msinn
26 Nov 2010, 3:52 AM
Ok, client-side works as aspected, and params are sent aspected too, now I'm focused on server side!! My trouble was to link the store correctly.

An extra question, anyone has developed a filter using ExtComboBox? (using a store to get remote data)....

It is the same as above with the filter example

in your Column:



,{header : 'State', dataIndex : 'STATE', editor : stateCombo , renderer : comboRenderer(stateCombo)}

comboRenderer: http://dev.sencha.com/deploy/dev/docs/?class=Ext.form.ComboBox

your combobox store



var stateStore = new Ext.data.JsonStore({
autoDestroy: true,
url: 'getStates.php',
root: 'rows',
fields: ['STATE', 'NAME_ENGLISH'],
autoLoad: false
});

your combobox



var stateCombo = new Ext.form.ComboBox({
name: 'STATE',
width: 200,
fieldLabel: 'State',
title:'States',
emptyText: 'Select state',
mode: 'local',
store: stateStore,
displayField: 'NAME_ENGLISH',
valueField: 'STATE',
typeAhead: true,
forceSelection: true,
triggerAction: 'all',
hiddenName: 'STATE',
hiddenId:'comboId'
});

filippo.ferrari
26 Nov 2010, 4:49 AM
,{header : 'State', dataIndex : 'STATE', editor : stateCombo , renderer : comboRenderer(stateCombo)}

comboRenderer: http://dev.sencha.com/deploy/dev/docs/?class=Ext.form.ComboBox



The above is the column configuration? And what about filter configuration? What's "comboRenderer" ??

filippo.ferrari
26 Nov 2010, 4:54 AM
With my request: "a filter using Ext.ComboBox" I mean a new filter type that have comboBox as input field, a comboBox linked to a remote store.

msinn
26 Nov 2010, 5:19 AM
With my request: "a filter using Ext.ComboBox" I mean a new filter type that have comboBox as input field, a comboBox linked to a remote store.

theres just list, this extension doesn't support a combobox, so far as I know

msinn
26 Nov 2010, 5:11 PM
With my request: "a filter using Ext.ComboBox" I mean a new filter type that have comboBox as input field, a comboBox linked to a remote store.

Hi,
there was somethig for an older version of GridFilters, maybe you can debug and update it, give a try.

http://www.sencha.com/forum/showthread.php?14503-Grid-Filter-(Plugin)&p=314342#post314342

Fabyo
29 Nov 2010, 5:32 AM
Can someone help me with the button on the clean filters?

leowyatt
30 Nov 2010, 3:20 AM
I've been using this filter with the checkbox selection model but if the user checks rows and then filters data the rows are no longer checked. If there anything in particular I need to do to get it to save which check boxes have been checked?

leowyatt
30 Nov 2010, 3:20 AM
Can someone help me with the button on the clean filters?

help in what way?

Fabyo
30 Nov 2010, 3:53 AM
post # 161

http://www.sencha.com/forum/showthread.php?76185-GridFilters-enhanced-filtering-for-grids&p=543598#post543598

msinn
30 Nov 2010, 4:06 AM
I've been using this filter with the checkbox selection model but if the user checks rows and then filters data the rows are no longer checked. If there anything in particular I need to do to get it to save which check boxes have been checked?

Hi, do you use it with local:false(default), as remote filtering?
Do you reload the datastore on filter changes? autoReload: true(default)

When both, than you have first to save all IDs (IdProperty in your Store) of the selected rows. After filtering you reselect the filtered Ids manually.

Take a look in GridFilters.js to bindStore: to understand how the extension binds the grid store, then you can try to select and reselect the rows on your store events 'beforeload' and 'load'

Its just an advice, try it to find out, if it works :)

goofy
4 Dec 2010, 7:17 PM
Hi,
someone have a idea/solution to save and restore GridFilters settings ?

Thanks

filippo.ferrari
7 Dec 2010, 6:19 AM
I've a problem... how to setup a numeric filter via script?

With .setActive(true) and .setValue(somevalue); I can set a filter for list filters but how to do it with a numeric filter (I want setup myfilter = somevalue).

Ebpo
7 Jan 2011, 10:46 AM
Hi!

I have a problem, not sure if this is where I'm supposed to post.
In the menu to filter numeric value (with gt, lt and eq), icons (=, >, <) are overlapping eachother and doubled.

Does anybody know what's the problem?
Thanks!

manilodisan
11 Jan 2011, 9:12 PM
I have autoReload set to true and an event placed on the beforedestroy method of the panel which contains my grid in order to clear the filters. In firebug, after closing that panel I get an error message stating that store is null which indicates that, after closing the panel, my filter tries to do a store reload for some reasons.


ordersPanel.on("beforedestroy", function() {
Ext.getCmp('ordersGrid').filters.clearFilters ();
return true;
});

This returns:

store is null: GridFilters.js line 503


Any ideas how to fix this?

ldonofrio
12 Jan 2011, 5:15 AM
Maybe it have something to do with a list filter, the plugin destroy the filter store onDestroy. I've a override that use the store autoDestroy flag to prevent this.



Ext.override(Ext.ux.menu.ListMenu, { destroy: function() { if (this.store && this.store.autoDestroy) { this.store.destroy(); } Ext.ux.menu.ListMenu.superclass.destroy.call(this); }});


I have autoReload set to true and an event placed on the beforedestroy method of the panel which contains my grid in order to clear the filters. In firebug, after closing that panel I get an error message stating that store is null which indicates that, after closing the panel, my filter tries to do a store reload for some reasons.


ordersPanel.on("beforedestroy", function() {
Ext.getCmp('ordersGrid').filters.clearFilters ();
return true;
});

This returns:

store is null: GridFilters.js line 503


Any ideas how to fix this?

sizemorew
13 Jan 2011, 11:47 AM
Not sure how useful anybody else will find it, but I did a custom modification to the DateFilter to give it the ability to search for null dates. Details are here:

http://www.sencha.com/forum/showthread.php?121082-Unable-to-Retrieve-Only-Null-Dates-with-Ext.ux.grid.GridFilters&p=560795#post560795

david777
31 Jan 2011, 8:16 AM
Hi...
A strange problem :
I have a problem with Firefox and Linux distribution when trying to type a string filter containing the character % :
It's like if I did nothing: the% character is not displayed in the text box, and no filter is applied.

Has anyone had this problem and knows the solution ?

mike2406
29 Mar 2011, 11:06 AM
I am developing an application that uses metadata-driven grids with gridfilters in a tabpanel.

Tabs are created dynamically via links.

Basically not sooo difficult :)
But unfortunately, the application can not handle gridfilters for more than one grid in a time.
Gridfilters are removed every time a new grid in a new tab is created and only the active tab got the gridfilter functionality.

Any ideas??

25405

hachie
8 Apr 2011, 2:57 AM
I have a Grid with GridFilter and when I show for the first times the grid it's work all fine.
If I close the grid and after I reopen it the GridFilter doesn't appears. Why?

The code is:

WINConsulente_GRID = Ext.extend(Ext.grid.EditorGridPanel, {
plugins: [new Ext.ux.grid.GridFilters({
filters:[
{type: 'string',dataIndex: 'cod'},
{type: 'string',dataIndex: 'username'/*,disabled: true*/},
{type: 'string',dataIndex: 'ragione_sociale'},
{type: 'string',dataIndex: 'telefono'},
{type: 'string',dataIndex: 'fax'},
{type: 'string',dataIndex: 'email'},
{type: 'string',dataIndex: 'website'},
{type: 'string',dataIndex: 'ref_nome'},
{type: 'string',dataIndex: 'ref_cognome'},
{type: 'string',dataIndex: 'ref_telefono'},
{type: 'string',dataIndex: 'ref_cellulare'},
{type: 'string',dataIndex: 'ref_email'},
{type: 'string',dataIndex: 'indirizzo'},
{type: 'string',dataIndex: 'cap'},
{type: 'string',dataIndex: 'frazione'},
{type: 'string',dataIndex: 'localita'},
{type: 'string',dataIndex: 'provincia'},
{type: 'string',dataIndex: 'cod_ateco'},
{type: 'string',dataIndex: 'desc_ateco'},
{type: 'string',dataIndex: 'cod_inail'},
{type: 'string',dataIndex: 'sede_inail'},
{type: 'string',dataIndex: 'iscrizione_inail'},
{type: 'string',dataIndex: 'pers1'},
{type: 'string',dataIndex: 'pers2'},
{type: 'numeric',dataIndex: 'pers3'},
/*{type: 'list',dataIndex: 'size',options: ['small', 'medium', 'large', 'extra large'],phpMode: true},*/
{type: 'date',dataIndex: 'data_creazione',beforeText: 'Prima del', afterText: 'Dopo il', onText: 'Il' },
{type: 'boolean',dataIndex: 'attivo'}
]
})],

mike2406
19 Apr 2011, 8:18 AM
I fixed it by myself...thanks for your support :)

cgi-bin
3 May 2011, 7:24 AM
I noticed something strange... when using a string filter, when clicking drop-down menu in the header to fill in the filter, if the search field is to the right of the drop-down, the filter "auto applies" (ie. there is a slight delay when I finish typing (or press enter) and the filter automatically checks the checkbox and the filter is applied).

However, if the column I want to filter is to the right side of the grid, and the filter field is forced to open to the left of the drop-down menu due to space limitations, the filter does NOT auto-apply if I pause typing or even press enter. I must manually check the check-box to have the filter applied.

I'm using autoReload:false and local:true in case it matters.

mfrancey
11 May 2011, 3:25 AM
Hi there!

I'd like to render the filter option list.
Instead of having just the text ('small','medium','large',...), I'd like to have an icon first:

Wanted code for rendered list:
<img src="./smallIcon.gif"> Small
<img src="./mediumIcon.gif"> Medium
<img src="./largIcon.gif"> Large

How to do this? Is it possible?

Thanks for your answer

Marc

cgi-bin
12 May 2011, 7:08 AM
Minor bug: If the data associated with a column in a grid had NULL values, you'd get:
Error: this.inputItem.getValue() is undefined
Source File: http://doug-dev.pacourts.us/js/ExtJS/ux/grid/GridFilters/filter/StringFilter.js
Line: 87

In StringFilter.js (Line 87) change:
return this.inputItem.getValue().length > 0;To:
return (this.inputItem && this.inputItem.getValue() && (this.inputItem.getValue().length > 0));

cgi-bin
12 May 2011, 12:11 PM
I seem to have solved both of my problems... if you try to specify a filter:{ } definition in the defaults:{} config for the column model, it doesn't actually apply correctly. Once I explicitly put the filter:{ type:'string' } for each an every column, everything worked as expected.

There is probably a bug somewhere, because it sort of worked before, just some strange behavior as explained.

Just wanted to post my findings to help save others the headache of stepping through the code.

hjones
31 May 2011, 7:52 PM
The link to a Grails implementation (by Mike Cantrell) on the first post of this thread appears to be no longer active.

http://mcantrell.wordpress.com/2008/...ds-and-grails/

Does anyone have access to or a copy of that code?

JSassy
15 Jun 2011, 5:49 AM
Hi, I'm using this GridFilter extension with ExtJs 3.2.1. and it's really useful, good work so far.

But I'm missing the options to search for <= and >=.
Furthermore, it is not possible to specify a filter for "empty" or "not empty" values. For example I would like to see all rows that don't have any value in the filtered column.

Are you planning to implement such filteroptions?

Or is there anybody who implemented some of them already and would like to share the code?
Thanks.

novaku
16 Jun 2011, 4:22 PM
Good morning,

based on this example : http://dev.sencha.com/deploy/ext-4.0.2a/examples/grid-filtering/grid-filter-local.html
I have difficulty to take "list" type of filters to fetch from store / ajax request, take a look at my script, what is wrong with it?
Is there any suggestion master?


//initial variable
var dataKategori = '';
Ext.Ajax.request({
url: '/CI/ecommerce/getKategoriBarang',
success: function(response){
dataKategori = response.responseText;
}
});

var filters = {
ftype: 'filters',
encode: true,
local: false,
filters: [{
type: 'list',
dataIndex: 'namaKategori',
=> options: [dataKategori],
phpMode: true
}, {
type: 'string',
dataIndex: 'namaBarang'
}, {
type: 'numeric',
dataIndex: 'harga'
}, {
type: 'numeric',
dataIndex: 'jumlahStock'
}, {
type: 'numeric',
dataIndex: 'sisa'
}]
};

cnicolas
1 Feb 2012, 4:54 AM
Hi !

When gridFilter is active, how I can retrieve the number of filtered rows in my store and if a specific record is filtered ?

Thank for your help.

WixSL
10 Feb 2012, 6:05 PM
Don't delete the filters, I need them for reuse:


Ext.ux.grid.GridFilters = Ext.extend(Ext.util.Observable, {
//...

/** @private */
constructor : function (config) {
config = config || {};
this.deferredUpdate = new Ext.util.DelayedTask(this.reload, this);
this.filters = new Ext.util.MixedCollection();
this.filters.getKey = function (o) {
return o ? o.dataIndex : null;
};
this.addFilters(config.filters);
//delete config.filters;
var filters = config.filters;
Ext.apply(this, config);
config.filters = filters;
},

cgi-bin
29 Feb 2012, 8:02 AM
I was frustrated that the ListMenu wasn't using the configured store's sorted values... so I fixed it:

Change ListMenu.js : in the onLoad function (line 116-ish).

Change:
for(var i=0, len=records.length; i<len; i++){
var item = new Ext.menu.CheckItem({
text: records[i].get(this.labelField),
group: gid,
checked: this.selected.indexOf(records[i].id) > -1,
hideOnClick: false});

item.itemId = records[i].id;
item.on('checkchange', this.checkChange, this);

this.add(item);
}
To:
store.each
(
function(rec)
{
var item = new Ext.menu.CheckItem
({
text: rec.get(this.labelField),
group: gid,
checked: this.selected.indexOf(rec.id) > -1,
hideOnClick: false
});

item.itemId = rec.id;
item.on('checkchange', this.checkChange, this);

this.add(item);
},
this
);

Basically the store's onLoad calls the filter's onLoad, but the filter's onLoad was using the raw store records. I changed it to use the store object directly which would already have the sorting done by that point (applySort is called before onLoad is fired).

This only uses the store's default sort (when sortInfo is defined). It does not change the menu if the store is re-sorted... if you want that, you'd probably need to have the filter listen for the store's dataChanged event and call the filter's onLoad again to re-create the menu.

radmila80
8 Nov 2012, 8:39 AM
I realize this response is too late, but maybe it will help someone else. In order to accept filter as a single parameter on java side, encode must be set to true.

nitingautam
3 Feb 2014, 4:43 AM
What about date based filtering, do we need to make column model config as date also?