PDA

View Full Version : ExtJS 4: Add filter on Columns in a Grid



lopezanibal
15 Aug 2011, 12:37 AM
Hi All,

Is there any example on how to setup in a simple way filtering on columns in a grid?
Thus just a grid, columns en filtering on columns.




Thx.


Anibal

skirtle
15 Aug 2011, 4:07 AM
There are many different styles of filtering. Here's a demo of one of them:

http://dev.sencha.com/deploy/ext-4.0.2a/examples/grid-filtering/grid-filter-local.html

The two key things are:


Is your filtering local or remote? i.e. is the filtering done in the browser or on the server?
Do you want to use filtering menus in the column headers or do you want a separate set of form fields for specifying the filter values?


This thread discusses techniques for remote filtering:

http://www.sencha.com/forum/showthread.php?143566

Local filtering is pretty easy. See the filter() method in the docs:

http://docs.sencha.com/ext-js/4-0/#/api/Ext.data.Store

If you need more help with this then just let us know what style of filtering you're trying to do.

beckdawg
15 Aug 2011, 7:43 AM
Just a heads up, I've had a lot of issues with filtering locally. Almost universally it is based on the store's cache. That's fine when you have a small data set but once you get over a certain number of records the draw time is super slow. So, to combat that we implemented paging. We also tried the buffered grid. The problem then becomes that filtering over a store's cache isn't generally what you want.

If you want the minimal effort path, I would recommend using FiltersFeature. Trying to implement filtering without that was a bit of a pain for me to work out. If you use that, paging, and sorting remotely should all jive well together.

First you need the js file which in the base download will be under examples/ux/grid/FiltersFeature. Second, make sure you include the file like so. You can put it wherever in your folder structure but you need to tell the loader where it goes because it's not in the src itself for ext js


Ext.Loader.setPath('Ext.ux', '../ux');
Ext.require([
'Ext.ux.grid.FiltersFeature'
...etc
]);


Basically you want to set up a filter like so


var filters = {
ftype: 'filters',
// 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: 'string',
dataIndex: '<indexName>'
},{
....etc
}]
};


Then on your grid you want to do this


var grid = Ext.create('Ext.grid.Panel', {
store: store,
features: [filters],


This isn't the only way to do it. However, this is likely the easiest way to do it.

lopezanibal
17 Aug 2011, 6:21 AM
Hi,

Thx. for the comments.
Really helpfull.


Now I am trying to call a function in the filer options that will set a variable that needs to be passed to the backend.
Is this possible in this way?

Thx.

Here is the code:

var filters = {
ftype: 'filters',
// field filtered
filters: [{ type: 'int', dataIndex: 'id_country' },
{ type: 'string', dataIndex: 'country' },
{ type: 'string', dataIndex: 'name' },
{ type: 'string', dataIndex: 'country_number' },
{ type: 'string', dataIndex: 'eeg_eva' }],
// encode and local configuration options defined previously for easier reuse
encode: false, // json encode the filter query
encodeFilters: function(filters) {
//
var where, qs, filter, field, value, compare, filterType;
//
for (i=0;i<count(filters);i++)
{
// reset
qs = '';
filter = '';
field = '';
value = '';
compare = '';
filterType = '';
//
filter = filters[i];
field = filter['field'];
value = filter['data']['value'];
compare = isset(filter['data']['comparison']) ? filter['data']['comparison'] : null;
filterType = filter['data']['type'];
//
switch(filterType){
case 'string':
qs = " AND " field " LIKE '%" value "%'";
Break;
case 'list' :
if (strstr(value,',')){
fi = explode(',',value);
for (q=0;q<count(fi);q++){
fi[q] = "'" fi[q]."'";
}
value = implode(',',fi);
qs = " AND " field " IN (" value ")";
}else{
qs = " AND " field " = '" value "'";
}
Break;
case 'boolean' :
qs = " AND " field " = " (value);
Break;
case 'numeric' :
switch (compare) {
case 'eq' :
qs = " AND " field " = " value;
Break;
case 'lt' :
qs = " AND " field " < " value;
Break;
case 'gt' :
qs = " AND " field " > " value;
Break;
}
Break;
case 'date' :
switch (compare) {
case 'eq' :
qs = " AND " field " = '" date('Y-m-d',strtotime(value)) "'";
Break;
case 'lt' :
qs = " AND " field " < '" date('Y-m-d',strtotime(value)) "'";
Break;
case 'gt' :
qs = " AND " field " > '" date('Y-m-d',strtotime($value)) "'";
Break;
}
Break;
}
//
where = where + qs;
}
return where;
},
local: false // defaults to false (remote filtering)
};

lopezanibal
18 Aug 2011, 9:05 AM
var filters = {
ftype : 'filters',
// encode and local configuration options defined previously for easier reuse
encode : false, // json encode the filter query
local : false, // defaults to false (remote filtering)
buildQuery : function (filters) {
//
var p_query, qs, filter, field, value, compare, filterType, count, len = filters.length;
//
for (i=0;i< len;i++)
{
// reset
qs = '';
filter = '';
field = '';
value = '';
compare = '';
filterType = '';
//
filter = filters[i];
field = filter['field'];
value = filter['data']['value'];
compare = filter['data']['comparison'];
filterType = filter['data']['type'];
//
switch(filterType){
case 'string' :
qs = " AND " + field + " LIKE '%" + value + "%'";
break;
case 'list' :
if (strstr(value,',')){
fi = explode(',',value);
for (q=0;q<count(fi);q++){
fi[q] = "'" + fi[q] + "'";
}
value = implode(',',fi);
qs = " AND " + field + " IN (" + value + ")";
}else{
qs = " AND " + field + " = '" + value + "'";
}
break;
case 'boolean' :
qs = " AND " + field + " = " + (value);
break;
case 'numeric' :
switch (compare) {
case 'eq' :
qs = " AND " + field + " = " + value;
break;
case 'lt' :
qs = " AND " + field + " < " + value;
break;
case 'gt' :
qs = " AND " + field + " > " + value;
break;
}
break;
case 'date' :
switch (compare) {
case 'eq' :
qs = " AND " + field + " = '" + date('Y-m-d',strtotime(value)) + "'";
break;
case 'lt' :
qs = " AND " + field + " < '" + date('Y-m-d',strtotime(value)) + "'";
break;
case 'gt' :
qs = " AND " + field + " > '" + date('Y-m-d',strtotime($value)) + "'";
break;
}
break;
}
//
p_query = p_query + qs;
}
return p_query;
},
// fields
filters : [{ type: 'int', dataIndex: 'id_country' },
{ type: 'string', dataIndex: 'country' },
{ type: 'string', dataIndex: 'name' },
{ type: 'string', dataIndex: 'country_number' },
{ type: 'string', dataIndex: 'eeg_eva' }]
};

lopezanibal
18 Aug 2011, 9:49 AM
var filters = {
ftype : 'filters',
// encode and local configuration options defined previously for easier reuse
encode : false, // json encode the filter query
local : false, // defaults to false (remote filtering)
buildQuery : function (filters) {
//
var p_query, qs, filter, field, value, compare, filterType, count, len = filters.length;
//
for (i=0;i< len;i++)
{
// reset
qs = '';
filter = '';
field = '';
value = '';
compare = '';
filterType = '';
//
filter = filters[i];
field = filter['field'];
value = filter['data']['value'];
compare = filter['data']['comparison'];
filterType = filter['data']['type'];
//
switch(filterType){
case 'string' :
qs = " AND " + field + " LIKE '%" + value + "%'";
break;
case 'list' :
if (strstr(value,',')){
fi = explode(',',value);
for (q=0;q<count(fi);q++){
fi[q] = "'" + fi[q] + "'";
}
value = implode(',',fi);
qs = " AND " + field + " IN (" + value + ")";
}else{
qs = " AND " + field + " = '" + value + "'";
}
break;
case 'boolean' :
qs = " AND " + field + " = " + (value);
break;
case 'numeric' :
switch (compare) {
case 'eq' :
qs = " AND " + field + " = " + value;
break;
case 'lt' :
qs = " AND " + field + " < " + value;
break;
case 'gt' :
qs = " AND " + field + " > " + value;
break;
}
break;
case 'date' :
switch (compare) {
case 'eq' :
qs = " AND " + field + " = '" + date('Y-m-d',strtotime(value)) + "'";
break;
case 'lt' :
qs = " AND " + field + " < '" + date('Y-m-d',strtotime(value)) + "'";
break;
case 'gt' :
qs = " AND " + field + " > '" + date('Y-m-d',strtotime($value)) + "'";
break;
}
break;
}
//
p_query = p_query + qs;
}
return p_query;
},
// fields
filters : [{ type: 'int', dataIndex: 'id_country' },
{ type: 'string', dataIndex: 'country' },
{ type: 'string', dataIndex: 'name' },
{ type: 'string', dataIndex: 'country_number' },
{ type: 'string', dataIndex: 'eeg_eva' }]
};

skirtle
18 Aug 2011, 2:08 PM
A few of thoughts.

I don't see where you initialize p_query. It starts off undefined and then you start doing string concatenation on it. This is unlikely to get you the string you want.

It also seems that you're returning p_query from buildQuery. This needs to be an object containing request parameters, not a string. It will be merged with the other parameters just before the Ajax request is sent off.

I also worry that you seem to be building some sort of SQL-like query in JavaScript. I hope you aren't planning on sending this directly through to a database: the server must always be responsible for building queries to the database for security reasons.

lopezanibal
23 Aug 2011, 1:33 AM
Hi All,

Problem solved when using the following:

return {p_filter: Ext.encode(proc_filters)};


Thx.

skirtle
23 Aug 2011, 1:49 AM
Could you please mark the thread as Answered?