PDA

View Full Version : Grid Filter (Plugin)



Pages : [1] 2 3 4

ambience
5 Oct 2007, 5:36 PM
Moderator edit: There's a 3.x version in svn now for those interested, click here (http://extjs.com/forum/showthread.php?t=76185).

Example: http://ccinct.com/lab/filter-grid/

I am excited to hear that a number of people have started using / extending the filters. If you have an extension (like some sort of panel based filter configuration) PM me with a link to the related thread and I will link it here. Thanks to every one who has helped bang out bugs and assisted newer users.

Also, I would like to credit ControlPath, the company that pays for my time =) The filters were developed to support an ongoing effort to transition the product to a 100% Ext UI and they were kind enough to let me share the code with you guys.

Server Side Code
Due to copyright issues I cannot share my implementation of the server side code (written in Java), and the PHP is to entangled in a bigger framework / hacked together to share. If you have an implementation you would like to share, PM me with the files and I will link them here.

PHP

http://www.vinylfox.com/extjs/grid-filter-php-backend-code.php - Thanks VinylFox


Ruby on Rails

http://extjs.com/forum/showthread.php?p=77326#post77326 - Thanks Zyclops
http://extjs.com/forum/showthread.php?p=176596#post176596 - Thanks Rotomaul


Python

http://www.debatablybeta.com/posts/using-extjss-grid-filtering-with-django/ - Thanks Matt


Grails

http://mcantrell.wordpress.com/2008/08/22/extjs-grids-and-grails/ - Thanks Mike


Initial Release

Grid filters now function as a plugin for the grid. As a result you can use them in conjunction with custom views (like grouping).
List filters are now much more robust in that you can provide them with a Ext.data.Store to load their options the first time they are shown.
This version does not have a a dynamic loader included, read the source to find out where to put yours (documented).
The way filters are configured has changed ever so slightly.
Now 100% Ext (Prototype-free).


Version 0.2

Local filtering can now be enabled by passing the 'local: true' as a config value
Fixed some of the filters setValue functions.
Stateful mode can now be enabled by passing a string value for the config option 'stateId'. This may be updated in the next Ext code push to store this information when the grid saves/restores its state. However, the events required are not part of the current beta (I think they are in SVN however)
Add an 'autoReload' field / config option that defaults to true. Set this to false if you wish to prevent the datastore from being reloaded when you make changes to the filters.


Version 0.2.1 (Minor update, thanks for the feedback)
Bug Fixes

Date filters will disable conflicting date ranges [Thanks hendricd (http://extjs.com/forum/member.php?u=8730)]
Added missing super constructor line to Filter [Thanks hendricd (http://extjs.com/forum/member.php?u=8730)]
Boolean filters now use uniqu radio group IDs (so you can have more then one!) [Thanks olive38 (http://extjs.com/forum/member.php?u=15429)]


Enhancements

Added a 'serialize' event to the Filter class. Using this you can attach additional parameters to serialization data before it is encoded and sent to the server.
You can pass the GridFilters object as a plugin to the paging toolbar and it will reset the page to 1 whenever you update the filters.
Boolean filters take a defaultValue config parameter. Set this to null if you do not want either option to be checked by default.


Version 0.2.2, 0.2.3, 0.2.4, 0.2.5
Bug Fixes

Fixed an issue with numeric fields displaying "NaN" initially in RC1 [Thanks JeffHowden (http://extjs.com/forum/member.php?u=4)]
Fixed an issue with filter application in the absence of request options [Thanks JorisA (http://extjs.com/forum/editpost.php?do=editpost&postid=70377)]
Date format is now forwarded to the date selectors [Thanks hendricd (http://extjs.com/forum/member.php?u=8730)]
Small bug fix with filters being activated before a load event on grids with the filters used as a plug in to the paging tool bar *inhale* [Thanks hendricd (http://extjs.com/forum/member.php?u=8730)]
Fixed a global namespace leak. [Thanks hendricd (http://extjs.com/forum/member.php?u=8730)]
Reload now cancels the deferred update. [Thanks ericwaldheim (http://extjs.com/forum/member.php?u=50)]
Local string filtering is now case insensitive . [Thanks robasi (http://extjs.com/forum/member.php?u=5316)]


Version 0.2.6
Bug Fixes

Removed a console.log in applyState(), oops >.<


Enhancments

The filter collection will now bind to the 'beforestaterestore' and 'beforestatesave' events in order to be stateful. Set your stateId on the associated grid.
Future versions will now include the version number in the header of GridFilters.js for your convenience


Version 0.2.7 June 4th, 2008
Enhancments

Add some localization support (post (http://extjs.com/forum/showthread.php?p=149052#post149052)) [Thanks wm003 (http://extjs.com/forum/member.php?u=13648)]
Tweeked EditableItem to have better icon support (post (http://extjs.com/forum/showthread.php?p=152627#post152627)) [Thanks AlxH (http://extjs.com/forum/member.php?u=4262)]
Added green tinted column header graphics and CSS classes for filtered columns
Icons are now all defined as styles in the resources/style.css file. You'll need to link to this in order to have them and get the new column header style. (no more need for prototype changes)


Version 0.2.8 August 22nd, 2008
Enhancments

Refactored ListFilter.js to use a new Ext.ux.menu.ListMenu component.
I've included Ext.ux.menu.TreeMenu, I can't really offer allot of support for it, but it's what we use for tree filters.


Bug Fixes

Fixed text selection and general carrot wonkyness in Firfox [Big Thanks to Steffen Hiller (http://extjs.com/forum/member.php?u=30124)]
You can now use apostrophes in Firefox 3 o.O

krycek
5 Oct 2007, 11:53 PM
=D>
Perfect. I can't imagine a better way to do that.
But I think I've found a bug, try to do as follow:
1. Resize the width of one column making the last column not visible on the grid panel (a horizontal scrollbar will be shown)
2. Go to the second page
3. Create a filter in the "Visible" column to show just "No" visibles records

After doing that I can't remove this filter anymore because the scrollbar is gone and the grid will no longer show any data because I'm on the second page that has no records.

In this particulary case, going back to the first page after any filtering, solves the problem. But what if after setting a filter on the last column made the grid show no records? In this case I wouldn't be able to remove the filter anymore.

ejetorix
6 Oct 2007, 1:18 AM
Fantastic job Ambience.

BTW, problems like krycek has noticed, are the reason for what i prefer a separate panel/region/whatever for filtering, instead of rendering it on columns menu.

Thank you for porting it to 2.0 branch in so little time.

Foggy
6 Oct 2007, 1:25 AM
Excellent work, thanks for sharing ;)

6epcepk
6 Oct 2007, 4:18 AM
Waiting for beta-version =)
Thanks!

ambience
6 Oct 2007, 10:53 AM
In this particulary case, going back to the first page after any filtering, solves the problem. But what if after setting a filter on the last column made the grid show no records? In this case I wouldn't be able to remove the filter anymore.

I agree that this is a problem. However I think that it may also be a small shortcoming in the base grid widget. I believe that a scrollbar should be present if the headers exceed the current view port and there is no data. I may be able to convince the paging tool bar to go to the first page by firing the appropriate events on the store when the filter configuration has changed and will look into that.

As a small work around, you could add a 'clear filters' button to your paging tool bar and bind its handler to filters.clearFilters(). If you wanted to get even more fancy, you could build a menu button that had items for each of the configured filters. I will add a 'filteradded' event to the GridFilters to help facilitate this.

Thanks for the feedback.

jack.slocum
6 Oct 2007, 12:09 PM
Great work ambience. Thank you for sharing, I am sure there are many who will find this useful!

franklt69
6 Oct 2007, 1:29 PM
very cool the filter, is there any way to do filter in the side client only for instance or it is only to server side?

regards
Frank

osamaao
7 Oct 2007, 3:30 AM
Hello,

Thanks for this nice filter feature.
I have a question please, I am new to extjs and I am trying to make an example running, I am using your filter-grid, DWR and Spring.

The problem is that I can't read the filter parameter on the Java side.. I am not sure of the parameter name. shouldn't it be "filters"?

Appreciating your help.

ambience
7 Oct 2007, 10:55 AM
By default the field is 'filter', with out the 's'. But that is configurable with the 'paramPrefix' confg option. For example:


plugins: new Ext.ux.grid.GridFilters({paramPrefix: 'omgBearIsDriving'});


Additionally, the filter param will be expressed as an array of objects for example:


filter[0][data][type]=string
filter[0][data][value]=Geek
filter[0][field]=name
filter[1][data][type]=list
filter[1][data][value]=medium,large,extra large
filter[1][field]=size


If you wish to change how the data is structured and sent to the server you can either extend GridFilters and overload the 'buildQuery' function or pass a new function as config option:



plugins: new Ext.ux.grid.GridFilters({
buildQuery: function(filters){
var p = {};
for(var i=0, len=filters.length; i<len; i++){
// Custom filter serialization
}

return p;
}
});

galdaka
7 Oct 2007, 12:18 PM
Excellent work!! Thanks for share!!

ambience
7 Oct 2007, 2:52 PM
very cool the filter, is there any way to do filter in the side client only for instance or it is only to server side?

regards
Frank

Sorry I missed your question until now. I will be looking into a 'local: true' config option soon. In theory the Ext.data.Store.filterBy function should be robust enough to allow me to do this, I just need to implement support for it on the filters. Perhaps something along the lines of Ext.ux.grid.filter.Filter.validateRecord(record).

AlxH
8 Oct 2007, 12:09 AM
Hi ambience!

Great work! Thanks!

Im trying to use this filters in an autogrid (which reconfigures itself with metadata from server). Currently there seems to be a problem with calling addFilter() in the onMetaChange event of the grids store.
I cant see why the call of addFilter doesnt return, it just quits the onMetaChange event.

Any hint?

ambience
8 Oct 2007, 8:08 AM
Hi ambience!

Great work! Thanks!

Im trying to use this filters in an autogrid (which reconfigures itself with metadata from server). Currently there seems to be a problem with calling addFilter() in the onMetaChange event of the grids store.
I cant see why the call of addFilter doesnt return, it just quits the onMetaChange event.

Any hint?

My first guess is that it is unable to find the filter type you are requesting and is throwing an exception which is getting swallowed some where. If you uncomment the try catch block inside the addFilter method and have firebug it should alert you to this case.

GridFilters does not load filters automagicly any longer. It is the responsibility of the getFilter method to locate and return the class for a requested filter. If you would like to enable dynamic loading of filters, overwrite this method with some form of synchronous script loader and return with the loaded filter class.

andrei.neculau
8 Oct 2007, 9:14 AM
For some reasons, it's impossible to reach your site.
Can you please attach the plugin's source to the main post of this thread? Thanks in advance

AlxH
8 Oct 2007, 9:21 AM
My first guess is that it is unable to find the filter type you are requesting and is throwing an exception which is getting swallowed some where. If you uncomment the try catch block inside the addFilter method and have firebug it should alert you to this case.

GridFilters does not load filters automagicly any longer. It is the responsibility of the getFilter method to locate and return the class for a requested filter. If you would like to enable dynamic loading of filters, overwrite this method with some form of synchronous script loader and return with the loaded filter class.


Thanks for your quick answer.
Sorry, I didnt write the hole story: The filters are cleanly applied by addFilter.
The problem is when a value is supplied to the addFilter argument.
Seems to be that a value will cause the grid to be reloaded, thats of cause not quite useful while the grid currently loading.
I wanted to have a preset value when the data for the grid is loaded.
That way I want to achieve a state saving/restoring for the filters.


(Sorry for my bad english)

Greetings

ambience
8 Oct 2007, 10:48 AM
For some reasons, it's impossible to reach your site.
Can you please attach the plugin's source to the main post of this thread? Thanks in advance

Not sure what the problem is. But here you go =)

AlxH
8 Oct 2007, 10:41 PM
Is there an easy way to preset the filters initial values, without triggering the events, so that the grid doesnt get reloaded?



Thanks for your quick answer.
Sorry, I didnt write the hole story: The filters are cleanly applied by addFilter.
The problem is when a value is supplied to the addFilter argument.
Seems to be that a value will cause the grid to be reloaded, thats of cause not quite useful while the grid currently loading.
I wanted to have a preset value when the data for the grid is loaded.
That way I want to achieve a state saving/restoring for the filters.


(Sorry for my bad english)

Greetings

ambience
9 Oct 2007, 8:44 AM
Is there an easy way to preset the filters initial values, without triggering the events, so that the grid doesnt get reloaded?

Sorry I didn't have time to really fully address your issue. It's a bit of a hack, but you could call gridFilter.deferredUpdate.cancle(); immediately after you add your filters / set values.

I'll see if I can come up with something a bit more elegant in a future version.

ambience
9 Oct 2007, 10:08 AM
BTW, problems like krycek has noticed, are the reason for what i prefer a separate panel/region/whatever for filtering, instead of rendering it on columns menu.

As this seems to be a common criticism (esp from ejetorix ;)), I just want to take a moment to defend my decisions =)

While I agree the filters under the headers are perhaps more comfortable for users who are familiar with Excel, this method simply does not provide the space / flexibility we (the people at my company) need. For example, one of our columns represents an object in a directed acyclic graph. For which we provide the ability to filter on name, id range, or by selecting the object in a tree (rendered in place) and optionally include all children. One or more of these options may be active at any given time.(Screenshot 1&2) Or, in a much more simple example you have the list filter which can allow for the selection of one or more items to filter by. With out the filter menu, these options would be far to complex to express in the limited space under the headers. Additionally, chances are that if a grid is filtered it is because a user has chosen to filter it and I feel that having that information constantly displayed verbosely is unneeded clutter. Especially when, in the case of commonly filtered fields in a complex layout, you can us listeners and API driven filter activation to provider richer feedback about what the data shown represents (Screenshot 3)

Furthermore, I feel that the logical 'binding' of filters to an existing visual representation of the data key (the column header) is much easier for people to understand then disjoint spreadsheet of filters. While a separate tab could provide compound column filters and additional flexibility (AND / OR instead of just and); it has been our experience (as we've developed similar panels in the past) that that kind of power is confusing to must users and only leveraged by ... well mostly just the developers =\

I do appreciate feedback and will try to incorporate what I can into the filters to make them better. However (there's always a however), I am fairly confident in my decision to make them menu driven as opposed to panel/tab driven. This does not preclude a panel based tie-in. It simply means I my self will most likely not be developing it.

Screenshots:
Screenshot 1
http://ccinct.com/lab/screenshots/tree.png

Screenshot 2
http://ccinct.com/lab/screenshots/category_menu.png

Screenshot 3
http://ccinct.com/lab/screenshots/overview.png

kfuglsang
10 Oct 2007, 2:11 AM
Hi everyone,

I would also like to know if it would be possible to do the filtering on the client side rather than using a server-side call?

AlxH
10 Oct 2007, 9:35 AM
Sorry I didn't have time to really fully address your issue. It's a bit of a hack, but you could call gridFilter.deferredUpdate.cancle(); immediately after you add your filters / set values.

I'll see if I can come up with something a bit more elegant in a future version.

Thank you for your help! "deferredUpdate.cancel()" did the trick.
But I solved another issue i had. setValue() cannot be called in the "metachange" event of the grids store, because of conflicting events, so i did it in the "load" event - It took me hours to find out.

To accomplish the state saveing/restoring i extended the GridFilters-class by a "setFilterData()" method, which does the opposite of "getFilterData()" by another set of "unserialze()" methods of the filter-type-classes.
If you are interested i can post the code.

lyardson
10 Oct 2007, 12:08 PM
Hi ambience,

Your filter works well,thanks for posting such a wonderful code
I m newbie and am learning through your code
so can i get a PHP file(ie action.php)so that i can try fetch from my database

Thanks in advance.:)

ambience
11 Oct 2007, 8:19 AM
AlxH: Sure, post away. I am working on a grid state manager plugin myself that will have similar functionality. Though, I plan on using the setValue function to restore the state.

Lyardson: I have attached the two important files for parsing the filters and generating the required SQL. They are components of a much larger frame work which is losely based on WACT, so they won't function as is. But hopefully they should point you in the right direction =)

franklt69
11 Oct 2007, 5:09 PM
Hi ambience, the filter is very good, is possible to add a features where the user can build for each column the conditions, and then save/load it will be very good, because is hard when you use a filter with several columns, make always the filter, I think will be good to to a clear filter, where, all condition for each columns can remove

regards
Frank

wm003
14 Oct 2007, 7:13 AM
Very well done filter! :)

If you dont want/like to display filtering in a separate area(e.g. unter the colum headers as mentioned before), what about just _displaying_ a little filter-symbol, if the column is filtered or not? This way, you dont need to check each column menu if _some_ filter is set or not and you can see immediatly, if the whole list is filtered somewhere.

Just like the little triangle-symbol displaying in the header when the list has been sorted as/descending. That would help a lot i think.

Also, the "save-my-filter" option would be very nice, but i guess this is something every developer using ext has to code this by himself. Just a little property like a ".getAllColumnFiltersInAJSONString" would be helpful within your plugin (maybe something like this is already included, i didn't check the whole api yet...is it?)

6epcepk
14 Oct 2007, 10:44 AM
Anybody using those php filter files?
Any source code of use?)

JeffHowden
14 Oct 2007, 6:03 PM
[...]If you dont want/like to display filtering in a separate area(e.g. unter the colum headers as mentioned before), what about just _displaying_ a little filter-symbol, if the column is filtered or not?[...]

Visual feedback of a filtered column is already supported. Notice when you filter a column the text changes to bold/italic. This is achieved by adding the class "ux-filtered-column" to the column header. In the CSS, this is defined as:


.x-grid3-hd-row td.ux-filtered-column {
font-style:italic;
font-weight:bold;
}

Should you decide this isn't enough feedback for your users, it'd be a piece of cake to apply your own styling via the "ux-filtered-column" class.

ambience
15 Oct 2007, 9:55 AM
Jeff: Thanks for fielding that question. You can also customize what class is applied to the filter header by passing the filterCls config value with a different class name.

I have updated the source on the demo page and will also be attaching the source to the OP. Updates are as follows:

Local filtering can now be enabled by passing the 'local: true' as a config value
Fixed some of the filters setValue functions.
Stateful mode can now be enabled by passing a string value for the config option 'stateId'. This may be updated in the next Ext code push to store this information when the grid saves/restores its state. However, the events required are not part of the current beta (I think they are in SVN however)
Add an 'autoReload' field / config option that defaults to true. Set this to false if you wish to prevent the datastore from being reloaded when you make changes to the filters.


That's it for now, enjoy.

P.S. As requested, future updates will appear in the OP.

wm003
15 Oct 2007, 10:10 AM
Should you decide this isn't enough feedback for your users, it'd be a piece of cake to apply your own styling via the "ux-filtered-column" class.


Oh, thanks for the info! Of course, that will do the trick :D

andrei.neculau
16 Oct 2007, 6:29 AM
For the sake of logic-keeping, can you please edit the first post of this thread, and attach the source.zip to that one, and also keep a changelog?

Otherwise, we will start seeing 1,2,3,4,5,6,... posts with source.zip attached to each, and with some fixes/enhancements announcements.

Thanks in advance

Troy Wolf
19 Oct 2007, 11:01 AM
That is some beautiful extension sweetness. Thanks for sharing this!

At approximately 1:15PM CST on 10/19/2007, I downloaded the source from the first post in this thread. I applied it to my grid using the source index.html as an example. My grid loads successfully, and my columns now have appropriate "Filter" items in the menus along with the new grouping items.

When I select "Group By This Field" or "Show in Groups" for any column, I get this error:


B[D].firstChild.style has no properties
http://myserver/ext-all.js
Line 142


Also, "Group By This Field" and "Show in Groups" appear to do the same thing. What's the difference? Why both?

debutant
19 Oct 2007, 2:15 PM
Hello everyone,
I am new to Ext and I am trying to use this plugin in combination with Autogrid plugin so I can load the meta data from the server. I got it to load the meta data but the paging bar is not loading, does anyone know how to fix this please.

Phunky
20 Oct 2007, 12:07 AM
This plugin looks great, i cant wait to dive in and test this at work on Monday :)

ambience
20 Oct 2007, 8:12 AM
Troy: This may be a silly question, but do you get the same error without the filter plugin? All I can really tell from that debug information is that the problem appears to be with the Ext Core library, which the groupable components are part of. It may still be the filters fault, but I am not modifying the structure of the grid's HTML in any way that would effect other components. Also, in the future it would be helpfull if you included ext-all-debug.js as the 'B[D]' element is a compressed versions of something much more verbose (read helpfull) and it is quite difficult to decipher the compressed lines of the ext-all.js file.

Troy Wolf
22 Oct 2007, 5:06 AM
Troy: This may be a silly question, but do you get the same error without the filter plugin?
:"> Not a silly question. I'm ashamed to say that I had never used a GroupingStore or a GroupingView before trying your grid filter extension. So I was trying 2 new things at once.

When I simply use the Ext 2.0 GroupingStore and GroupingView on my grid, I get the same error--as you suspected, it has nothing to do with your extension.

So now it's time to back things down to as simple a grid as I can to see if I can isolate the issue to something specific that I'm doing.

Thanks. ~o)

FOLLOW-UP
I never found exactly what I was doing wrong, but I do have this extension working now with my Ext2.0 grid using local filtering and both list and string types. Thanks!

chernomorez
22 Oct 2007, 11:05 AM
Ambience,
great plug-in!

Few questions:
1) Index.html refers to JSonResponseReader.js, but that file is not included in the source zip. Can you post the source of that file?
2) Could you also post the source of the .php file.

Thanks again!

MatjazH
22 Oct 2007, 1:47 PM
\:D/ =D>

jay@moduscreate.com
22 Oct 2007, 5:02 PM
Ambience,
great plug-in!

Few questions:
1) Index.html refers to JSonResponseReader.js, but that file is not included in the source zip. Can you post the source of that file?
2) Could you also post the source of the .php file.

Thanks again!

it seems to work without it

lupin85.luca
23 Oct 2007, 6:55 AM
Very nice plugin!
I've used it succesfully and so ... =D>

But...
I want to display the entire column (the header and the cells under this column) with a background color, in order to mark that this field is just filtered.
:-?
Perhaps it's a css problem, I'm not sure. If so, apologize me.

Thanks

debutant
23 Oct 2007, 10:32 AM
Hello everyone,
Does anyone has an example of ruby code that builds the sql conditions according to the filter conditions sent to the controller?

like filtering by a string or boolean?

Thank you for the help

ambience
23 Oct 2007, 12:53 PM
Very nice plugin!
I've used it succesfully and so ... =D>

But...
I want to display the entire column (the header and the cells under this column) with a background color, in order to mark that this field is just filtered.
:-?
Perhaps it's a css problem, I'm not sure. If so, apologize me.

Thanks

The plugin does not currently allow you to apply styles to the whole column, but that's a great idea. I'll see about adding the support in a future version (although project objectives prevent me from working on the plugin very much beyond tweaks/bug fixes at the moment). However, you can register an event listener with the GridFilters object and apply/remove a class to the appropriate cells when a change occurs. You would most likely also want to bind the same update function to view updates. For example, your event listener could look like this (untested):


onFilterChange: function(filter){
var view = this.grid.getView();
var col = view.cm.findColumnIndex(filter.dataIndex);
view.mainBody.select('.x-grid-col-' + col)[filter.active ? 'addClass' : 'removeClass']('ux-filtered-column');
}

Zyclops
23 Oct 2007, 10:02 PM
Does anyone has an example of ruby code that builds the sql conditions according to the filter conditions sent to the controller?


Only since yesterday so it's pretty rough, my get_column_name sanatizes the column name by checking against the ActiveRecord models column_names.

This builds fine conditions for integers and strings


def filter_options(filter_hash, grid_settings)
filter_sql = []
values = []

#Return an empty hash if the filter is empty
return {} if filter_hash.nil?

filter_hash = filter_hash.delete_if {|key, value| value.blank? }
filter_hash.each do |column_number, filter_settings|
fs = nil

field = get_column_name(filter_settings[:field])
column_type = filter_settings[:data][:type]
value = filter_settings[:data][:value]
comparison = filter_settings[:data][:comparison]

case column_type
when 'numeric'
#todo: I might need to deal with floats at some point
value = value.to_i
case comparison
when 'gt'
fs = "#{field} > ?"
when 'lt'
fs = "#{field} < ?"
when 'eq'
fs = "#{field} = ?"
end
when 'string'
fs = "#{field} like ?"
value = "%#{value}%"
else
'Not Implemented'
end
unless fs.nil?
filter_sql << fs
values << value
end
end

if filter_sql.empty?
{}
else
{:conditions => [filter_sql.join(' and ')] + values}
end
end

lupin85.luca
23 Oct 2007, 11:41 PM
The plugin does not currently allow you to apply styles to the whole column, but that's a great idea. I'll see about adding the support in a future version (although project objectives prevent me from working on the plugin very much beyond tweaks/bug fixes at the moment). However, you can register an event listener with the GridFilters object and apply/remove a class to the appropriate cells when a change occurs. You would most likely also want to bind the same update function to view updates. For example, your event listener could look like this (untested):


onFilterChange: function(filter){
var view = this.grid.getView();
var col = view.cm.findColumnIndex(filter.dataIndex);
view.mainBody.select('.x-grid-col-' + col)[filter.active ? 'addClass' : 'removeClass']('ux-filtered-column');
}



Thank you for the suggestion - I'll try in a few days and I'll post if it works.
Thanks again.

lupin85.luca
24 Oct 2007, 6:03 AM
The plugin does not currently allow you to apply styles to the whole column, but that's a great idea. I'll see about adding the support in a future version (although project objectives prevent me from working on the plugin very much beyond tweaks/bug fixes at the moment). However, you can register an event listener with the GridFilters object and apply/remove a class to the appropriate cells when a change occurs. You would most likely also want to bind the same update function to view updates. For example, your event listener could look like this (untested):


onFilterChange: function(filter){
var view = this.grid.getView();
var col = view.cm.findColumnIndex(filter.dataIndex);
view.mainBody.select('.x-grid-col-' + col)[filter.active ? 'addClass' : 'removeClass']('ux-filtered-column');
}



I've tried for hours, reading the API and searching the forums but I can't apply a custom style (or better a css) to a whole column.

Maybe it's a very dumb question, but could you please explain me how can I set a css, class or inline style to a column???
Your code seems wrong or I cannot make it works on my application.
I think it's a very silly and annoying question, but in the forum nobody explain this.
In the API docs (2.0beta1) I found: "[...] the ability to apply a CSS class to all cells in a column through its id config option". But HOW???

Thank you again.

hendricd
25 Oct 2007, 10:42 AM
@Ambience - Nice job indeed. In fact, I've added it my 100% client side App (runs on CD, file systems etc), and combined with my turbo-charged version of Ext.ux.data.BufferedPagingMemoryProxy, it flys !

Since, I had to couple the filterchange and activation events to my local filter function, I ran across a couple of challenges with the events. But I have mods for them here \:D/:


In the base Filter class, something was missing for Observable which permits defining 'listeners' in the filter constructors directly:


Ext.ux.grid.filter.Filter = function(config){

Ext.apply(this, config);

this.events = {
/**
* @event activate
* Fires when a inactive filter becomes active
* @param {Ext.ux.grid.filter.Filter} this
*/
'activate': true,
/**
* @event deactivate
* Fires when a active filter becomes inactive
* @param {Ext.ux.grid.filter.Filter} this
*/
'deactivate': true,
/**
* @event update
* Fires when a filter configuration has changed
* @param {Ext.ux.grid.filter.Filter} this
*/
'update': true
};

Ext.ux.grid.filter.Filter.superclass.constructor.call(this);

this.menu = new Ext.menu.Menu();
this.init();

if(config && config.value){
this.setValue(config.value);
this.setActive(true, true);
delete config.value;
}

};

Then, for the DateFilter:

a) I patched a mechanism for firing activate/deactive when one of (before/after/on) filters were switched on/off (previously they all had to be on/off before the event would fire).

b) It also (tries to) tackles the issue of before and after dates out-of-range, if used in that fashion. The approach (may not be the best one) is to penalize the opposite side (before vs after) and set it's picker value to that of the offender and disable(uncheck) it. This guarantees that one of the filters functions properly and user sees what they've done wrong.

c) To support/enhance client/server-side date filtering, I also added the dateFormat string to the serializer. This was needed to support optional conversion is case comparing dates in the same format was required.

d) permit min/maxDates for the pickers passed in the filters contructor as well.



Ext.override(Ext.ux.grid.filter.DateFilter , {
maxDate : null,
minDate : null,
init: function(){
var pickerOptions = {minDate:this.minDate, maxDate:this.maxDate};
var dates = this.dates = {
'before': new Ext.menu.CheckItem({text: "Before", menu: new Ext.menu.DateMenu(pickerOptions)}),
'after': new Ext.menu.CheckItem({text: "After", menu: new Ext.menu.DateMenu(pickerOptions)}),
'on': new Ext.menu.CheckItem({text: "On", menu: new Ext.menu.DateMenu(pickerOptions)})};

this.menu.add(dates.before, dates.after, "-", dates.on);

for(var key in dates){
var date = dates[key];
date.menu.on('select', function( date, menuItem , value,picker){

date.setChecked(true);

if(date == dates.on){
dates.before.setChecked(false, true);
dates.after.setChecked(false, true);
} else {
dates.on.setChecked(false, true);

//going for a between dates operation?
if(dates.before.checked && dates.after.checked){

var badDate = (date == dates.before &&
value > dates.after.menu.picker.value) ?dates.after:null;

badDate || (badDate = (date == dates.after &&
value > dates.before.menu.picker.value )?dates.before:null );

if(badDate){
//set the 'opposing' offender's date
//to 'value' and disable for recovery
badDate.menu.picker.setValue(value);
badDate.setChecked(false,true);
}

}

/*
dates.before.menu.picker.minDate =
dates.after.checked ? this.getFieldValue('after') : null;
dates.after.menu.picker.maxDate =
dates.before.checked ? this.getFieldValue('before') : null;*/
}

this.fireEvent("update", this);
}.createDelegate(this, [date],0));

date.on('checkchange', function(date,checked){

this.active = null; //force a activate/deactivate event
//when on of (before/after/on) changes
this.setActive(this.isActivatable());
},this);
};
},
serialize: function(){
var args = [];
if(this.dates.before.checked)
args = [{type: 'date', comparison: 'lt', format: this.dateFormat, value: this.getFieldValue('before').format(this.dateFormat)}];
if(this.dates.after.checked)
args.push({type: 'date', comparison: 'gt', format: this.dateFormat, value: this.getFieldValue('after').format(this.dateFormat)});
if(this.dates.on.checked)
args = {type: 'date', comparison: 'eq', format: this.dateFormat, value: this.getFieldValue('on').format(this.dateFormat)};

return args;
}
});


And, here's a filtered column header style I was playing with...


.x-grid3-hd-row td.ux-filtered-column div {
background: url(/resources/images/find.png) no-repeat scroll right 2px ;
font-style: italic;
font-weight: bold;
}


Hey, choose 'em or lose 'em ;) but, what you've done is a fine example of class 'A' class-based development !

hendricd
26 Oct 2007, 11:44 AM
Here is the approach I've taken to set a classname for an entire grid column. The example is designed to work with GridFilter but you could use it just about anywhere.

It takes advantage of 2.0+ columnModel.renderers and the 'filterupdate' event generated by GridFilter:


First, setup a 'filterupdate' event handler for GridFilter's de/activation changes:


grid.on('filterupdate',function(GridFilter,filter){

var cm=this.getColumnModel();
var idx = cm.findColumnIndex(filter.dataIndex);

Ext.apply(cm.config[idx], //apply your current filter status to the column's config object
{ filterActive : filter.active
, filterClass:GridFilter.filterCls //default: 'ux-filtered-column'
});

},grid);
Now, the cool part. You'll want to run this block after all the custom renderers are defined for your columnModel.



var filterHook = function(value,p,record,rowIndex,colIndex,store ){
//scope is columnModel
var c= this.config[colIndex];

// p is the object that get's applied to the cell template,
// so we simply add the className to the cell's TD element during cell rendering

if(c.filterActive){p.css += ' ' + c.filterClass;}
};
//Only 'hooking' renderers where you have a Filter Column defined.
Ext.each(grid.filters.filters.keys,
function(filterName){ //scope is columnModel

var idx = this.findColumnIndex(filterName);

this.setRenderer(idx, this.getRenderer(idx).createInterceptor(filterHook,this));

}
,grid.getColumnModel());

and for this example, this is the corresponding CSS selector for the cheesy cell effects (modify to suit your needs):


td.x-grid3-col td.ux-filtered-column {

font-style: italic;
background-color:#98fb98;

}
Now, your column selector is applied even if you use the PagingToolbar.

Enjoy.

[UPDATED:] Simplified, no custom template definitions are required.

deependhulla
26 Oct 2007, 10:54 PM
Hi

Your filter works great,thanks for posting such a useful code
would suggest some points..
you filter works on multiple colum simultenously.

means we can apply multiple fitlers and they are actually passed to server-side program.
any idea or clue on how to have multiple sort orders for one can use sort with a,b,c,and more.

Thanks..for great code example and tool.
thanks in advance.

-Deepen Dhulla

lupin85.luca
29 Oct 2007, 7:53 AM
It seems it doesn't work in Ext2.0 beta1.
What is "templates"?
In the docs it doesn't exist. Maybe it's for 1.1 version only?!

Am I missing something?
Please, could you explain me?

Thank you very much

hendricd
30 Oct 2007, 1:17 PM
My original post (http://extjs.com/forum/showthread.php?p=78550#post78550)on this topic has been updated (and simplified). You don't even have to mess with defining a new cell rendering template.

galdaka
30 Oct 2007, 11:18 PM
Hi,

Excellent work. want to override "buildQuery" method for customice the query string that sends to server. What are the steps for begin?

Thanks in advance,

reaper.br
31 Oct 2007, 3:26 AM
Hi,

Excellent work. want to override "buildQuery" method for customice the query string that sends to server. What are the steps for begin?

Thanks in advance,

Just copy the original code (in gridFilters.js) and paste it inside ur GridFilters config options, as ambience (http://extjs.com/forum/member.php?u=865) explain here (http://extjs.com/forum/showthread.php?p=70683#post70683)

reaper.br
31 Oct 2007, 4:18 AM
I have a problem on the string filter.
It's not possible to add a ['] in the search input. E.g: [it's won't can't]. That will show as: [its wont cant].

I've just notice something else.
When i try to delete my search text, I can't select the whole phrase and press del. I have to keep pressing backspace.

Did i make any sense at all?
Thanks in advance.

olive38
31 Oct 2007, 7:24 AM
Hi Ambience,

I really love your plug-in, thanks, but...

I have two issues to report:

1) the most annoying one first: when I roll over the state menu of one of the boolean filter then the others are immediately filtering (with value 'No') even if I do not click one of the menu option I Intended to.
This happen the 1st time only a grid with several boolean filtered columns is rendered.
I try again after removal of ', checked: true' on line 5 in BooleanFilter.js.
Then it is a little better but when I change one the boolean filters state then the others are also switching immediately.

2) Inserting the following lines at the beginning of my Ext.onReady block does not do what it is intended for:
Ext.ux.menu.RangeMenu.prototype.icons = {
gt: '/wiposoft/site_media/js/ux/img/greater_then.png',
lt: '/wiposoft/site_media/js/ux/img/less_then.png',
eq: '/wiposoft/site_media/js/ux/img/equals.png'
};
To see the icons I need to change RangeMenu.js this way:
var fields = this.fields = Ext.applyIf(this.fields || {}, {
'gt': new Ext.ux.menu.EditableItem({
icon: '/wiposoft/site_media/js/ux/img/greater_then.png',
editor: new cls(typeof cfg == "object" ? cfg.gt || '' : cfg)}),
'lt': new Ext.ux.menu.EditableItem({
icon: '/wiposoft/site_media/js/ux/img/less_then.png',
editor: new cls(typeof cfg == "object" ? cfg.lt || '' : cfg)}),
'eq': new Ext.ux.menu.EditableItem({
icon: '/wiposoft/site_media/js/ux/img/equals.png',
editor: new cls(typeof cfg == "object" ? cfg.gt || '' : cfg)})
});

Thanks for your help.

Olive.

jojo_i
31 Oct 2007, 7:59 AM
Hello everyone,
I am new to Ext and I am trying to use this plugin in combination with Autogrid plugin so I can load the meta data from the server. I got it to load the meta data but the paging bar is not loading, does anyone know how to fix this please.

Its wery nice plugin, I will be really happy to add it to our autogrids, but
I have the same problem as this guy. I saw the conversation with user AlxH here (http://extjs.com/forum/showthread.php?p=70808#post70808)... is that the solution of this problem? I tryied it but does not working. Can you post some script, please? thanks

hendricd
31 Oct 2007, 11:33 AM
@Olive: Since default icons are attached(modifiable) via RangeMenu.prototype.icons, I believe just remove the offender here:



Ext.extend(Ext.ux.menu.RangeMenu, Ext.menu.Menu, {
fieldCls: Ext.form.NumberField,
fieldCfg: '',
updateBuffer: 500,
/*icons: { <-- This would override the prototype definitions
gt: '/img/small_icons/greater_then.png',
lt: '/img/small_icons/less_then.png',
eq: '/img/small_icons/equals.png'}, */

fireUpdate: function(){
this.fireEvent("update", this);
},


..which would (errantly) override the prototype for icons.

Works on my end now.

[I'll bet he just forgot to remove it, after moving the definitions to prototype. ;) ]

AlxH
31 Oct 2007, 11:35 AM
Its wery nice plugin, I will be really happy to add it to our autogrids, but
I have the same problem as this guy. I saw the conversation with user AlxH here (http://extjs.com/forum/showthread.php?p=70808#post70808)... is that the solution of this problem? I tryied it but does not working. Can you post some script, please? thanks

I added a few lines the autogrid (that was postet some time ago in another thread) to support loading of filterdata


Ext.grid.DynamicGridPanel = Ext.extend(Ext.grid.GridPanel, {
cellRenderers : {},

addRenderer : function(name, fn) {
this.cellRenderers[name] = fn;
},
initComponent : function(){
if(this.columns == null && this.cm == null)
this.columns = [{ id: 'dummy', dataIndex: 'dummy', width: 100}];
this.store = new Ext.data.GroupingStore({
proxy: new Ext.data.HttpProxy(new Ext.data.Connection({url: this.url})),
reader: new Ext.data.JsonReader(
{root: 'root', totalProperty: 'count', id: 'ID'},
[{name: 'dummy', mapping: '', type: 'string'}]
),
remoteSort: true
});
this.bbar= new Ext.PagingToolbar({
store:this.store,
pageSize: this.pageSize||20,
displayInfo: true,
displayMsg: '{0} - {1} / {2}',
emptyMsg: 'Keine',
});
Ext.grid.DynamicGridPanel.superclass.initComponent.call(this);

this.store.on("metachange", this.onMetaChange, this);
this.store.on("load", this.onLoad, this);

if(this.editLink) {
this.on('rowdblclick', this.onRowDblClick, this);
}
this.addEvents({"reconfigure":true});
},

onLoad: function(store,records) {
var meta=store.reader.meta;
if (meta && meta.filter) {
this.filters.setFilterData(meta.filter);
this.filters.deferredUpdate.cancel();
}
},
reconfigure: function(s,m) {
Ext.grid.DynamicGridPanel.superclass.reconfigure.call(this,s,m);
this.fireEvent("reconfigure");
},
onMetaChange : function(store, meta) {
var columns = [//this.expander,
this.checkModel];
var autoExpand = false;
var field = null;
this.filters.filters.clear();
for(var i=0; i<meta.fields.length; i++){
field = meta.fields[i];
if(field.header !== undefined){
if(this.cellRenderers[field.rendererName]) {
field.renderer = this.cellRenderers[field.rendererName];
} else if(this.cellRenderers["_"+field.name]) {
field.renderer = this.cellRenderers["_"+field.name];
}
if (!field.dataIndex) field.dataIndex = field.name;
if(!field.id) {
field.id = 'c' + i;
}
if (field.filter && !this.filters.getFilter(field.dataIndex) ) this.filters.addFilter({dataIndex:field.dataIndex,type:field.filter});
if(!field.width) {
field.width = 100;
} else if(field.width == "auto") {
autoExpand = field.id;
field.width = 100;
} else if(typeof field.width == 'string') {
field.width = parseInt(field.width);
}
delete field.name;
columns[columns.length] = field;
}
}
var cm = new Ext.grid.ColumnModel(columns);
this.getBottomToolbar().updateInfo();
if (meta.groupField) this.store.groupBy(meta.groupField); else this.store.clearGrouping();
this.reconfigure(this.store, cm);
}
});
Ext.reg('dynamicgrid', Ext.grid.DynamicGridPanel);



In the GridFilters Constructor, there should be an empty configuration possible:


Ext.ux.grid.GridFilters = function(config){
this.filters = new Ext.util.MixedCollection();
this.filters.getKey = function(o){return o ? o.dataIndex : null};
if (config && config.filters) {
for(var i=0, len=config.filters.length; i<len; i++)
this.addFilter(config.filters[i]);
}
this.deferredUpdate = new Ext.util.DelayedTask(function(){
this.grid.store.reload()
}, this);

delete config.filters;
Ext.apply(this, config);
};


To configure the initial filter configuration, i wrote in GridFilters


setFilterData: function(data){
for (var i=0; i<data.length; i++) {
this.getFilter(data[i].field).unserialize(data[i].data);
}
var view = this.grid.getView();
if(view) this.updateColumnHeadings(view);
},




And of course unserialize methods in the filter classes:


unserialize: function (arg) {
this.setValue(arg.value);
this.setActive(true,true);
}



This way I can pull metadata incl. filtervalues and grids data in one shot from server. The grid can configure itself and put filterdata on columns without having to pull data again from server.
You can get the grids config with some kind of:


var cm=this.grid.getColumnModel();
var ds=this.grid.getStore();
var cfg={root:'root', totalProperty:'count', id:'ID', sortInfo:{}, fields: [], pageSize:this.grid.pageSize };
var sortState = ds.getSortState();
if ( typeof(sortState) == "object" ) {
if ( ("field" in sortState) && ("direction" in sortState) ) {
cfg.sortInfo.field = sortState.field;
cfg.sortInfo.direction = sortState.direction;
}
}
cfg.groupField=ds.getGroupState();
cfg.filter=this.grid.filters.getFilterData();

for (var i = 0; i < cm.config.length; i++) {
var c=cm.config[i];
if (c.dataIndex) {
c.name=c.dataIndex;
cfg.fields.push(c);
}
}




I believe there are easier ways to do this, but it was my first try, and so far it works for me.
When filters and grids become fully "state aware" it might be a lot easier.

burned
31 Oct 2007, 12:44 PM
hello,

can you put funcional example in zip for download? I think many people would find this usefull.


sorry for my english.


Martin.

cobnet
31 Oct 2007, 10:15 PM
Very nice plugin, thanks much for sharing this!

As always someone comes along and has a problem, here is my current delima, lol!:

I have your filter plugin running perfectly as is, but I have added a combobox to my gridpanel header for additional filtering. The combobox has nothing to do with the column filtering in the grid.

1) When the grid first loads, I can see that the store load is processing the combobox's value and passing it along, no filter values. Nothing has been selected in the combobox, it sends the rendered value of the combobox.

2) If I then select a filter for a column and enter a value, the filter does not get passed on to the server by the grid. The store does attempt to load though with the combobox's value included.

3) However, if I then select a value in my combobox, everything gets passed along.

Is there some sort of initializing for the grid to know the filter is there? Like I said, it does filter, but only after actually selecting a value in the combo box?

Any leads would be great.
Mark

hendricd
1 Nov 2007, 4:22 AM
@cobnet - you might might to make sure that each attempt to 'enrich' the params block is handled progressively with Ext.apply (as GridFilter does):



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

},

You likely also have a beforeload handler defined somewhere to create a parameter for your combos' rendered value. There may be several other beforeload handlers called before/after yours is, that need the same consideration.

~o)

jojo_i
1 Nov 2007, 7:04 AM
to: AlxH. Thanks very much for postig you scripts, its great help to me, i try to do it with them

jojo_i
1 Nov 2007, 7:46 AM
to: AlxH. I tried it and its working perfectly like hell, great work, thank you another time:D

ambience
1 Nov 2007, 8:03 AM
I have a problem on the string filter.
It's not possible to add a ['] in the search input. E.g: [it's won't can't]. That will show as: [its wont cant].

I've just notice something else.
When i try to delete my search text, I can't select the whole phrase and press del. I have to keep pressing backspace.

Did i make any sense at all?
Thanks in advance.

The select all is a Firefox issue with floating text inputs that I have not been able to solve. The text IS actually selected, but the highlight will not show up. To add insult to injury, the carrot will also disappear in certain situations >.<

I'm looking into the other issue.

ambience
1 Nov 2007, 8:13 AM
@Olive: Since default icons are attached(modifiable) via RangeMenu.prototype.icons, I believe just remove the offender here:



Ext.extend(Ext.ux.menu.RangeMenu, Ext.menu.Menu, {
fieldCls: Ext.form.NumberField,
fieldCfg: '',
updateBuffer: 500,
/*icons: { <-- This would override the prototype definitions
gt: '/img/small_icons/greater_then.png',
lt: '/img/small_icons/less_then.png',
eq: '/img/small_icons/equals.png'}, */

fireUpdate: function(){
this.fireEvent("update", this);
},


..which would (errantly) override the prototype for icons.

Works on my end now.

[I'll bet he just forgot to remove it, after moving the definitions to prototype. ;) ]

Those lines of code are applying it to the prototype. The example prototypal overwrite works ... The only reason I can think that it wouldn't work is if the script in RangeMenu.js is being executed a second time thusly overwriting the overwrite ....:-?

hendricd
1 Nov 2007, 8:31 AM
The only reason I can think that it wouldn't work is if the script in RangeMenu.js is being executed a second time thusly overwriting the overwrite .Which would happen as soon as another column imposed another Rangemenu-based filter, like mine does ;)

ambience
1 Nov 2007, 9:01 AM
Instantiate you mean? Object instantiation wouldn't cause the Ext.extend to somehow reapply the overwrites to the prototype. Unless my understanding of z in Ext.extend(x, y, z) is severely flawed this leaves two possible scenarios:

You are instantiating the filters before your overwrite the prototype. In which case the fields have already been created and passed the default icon value. Thusly 'disconnecting' them from that value.
Or two, you are evaluating the script a second time, essentially refreshing the prototype to the default values.


I should note that the prototype overwrite doesn't have to happen in the onReady function. Just before you create your filters and after library itself is loaded.

hendricd
1 Nov 2007, 9:12 AM
When I get a chance, I'll examine the prototype chain at run-time. I'll let ya know what I find.. ;)

olive38
1 Nov 2007, 9:28 AM
Thank you Doug and Ambience for your help,

Il will try what you are suggesting.

But what is your opinion about my 1st problem ?
Could you please tell me if using more than one Boolean filter in one grid is working properly for you ?
This is a show stopper for me!

Olive.

hendricd
1 Nov 2007, 9:51 AM
Instantiate you mean? Object instantiation wouldn't cause the Ext.extend to somehow reapply the overwrites to the prototype. Unless my understanding of z in Ext.extend(x, y, z) is severely flawed this leaves two possible scenarios:
You are instantiating the filters before your overwrite the prototype. In which case the fields have already been created and passed the default icon value. Thusly 'disconnecting' them from that value.
Or two, you are evaluating the script a second time, essentially refreshing the prototype to the default values.I should note that the prototype overwrite doesn't have to happen in the onReady function. Just before you create your filters and after library itself is loaded.


Just browsed the RangeMenu prototype and it looks just fine. Your right, Ambience, the only way that should happen is if the script were loaded/evaled once again after prototype.icons were set..

@Olive- you been a bad boy ? ;)

hendricd
1 Nov 2007, 9:58 AM
But what is your opinion about my 1st problem ?
Could you please tell me if using more than one Boolean filter in one grid is working properly for you ?
Olive.


This looks to be the problem: Ambience:




Ext.ux.grid.filter.BooleanFilter = Ext.extend(Ext.ux.grid.filter.Filter, {
init: function(){
this.options = [
new Ext.menu.CheckItem({text: "Yes", group: 'boolean'}),
new Ext.menu.CheckItem({text: "No", group: 'boolean', checked: true})];

this.menu.add(this.options[0], this.options[1]);
That menu group needs to be unique across Filter instances, no ?

Perhaps:


group:this.menu.id+'boolean'

ambience
1 Nov 2007, 10:16 AM
Yep, just fixed it, thanks for catching it =) I also added a defaultValue parameter that defaults to 'false'. Set it to undefined or null if you do not want either to appear selected initially.

Ellevo
1 Nov 2007, 12:46 PM
How can i set a value to a specific filter at rendering time?

Thanks

hendricd
1 Nov 2007, 5:15 PM
{type: 'string', dataIndex: 'subject' ,value: 'find' }

cobnet
1 Nov 2007, 8:58 PM
@cobnet - you might might to make sure that each attempt to 'enrich' the params block is handled progressively with Ext.apply (as GridFilter does):



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

},

You likely also have a beforeload handler defined somewhere to create a parameter for your combos' rendered value. There may be several other beforeload handlers called before/after yours is, that need the same consideration.

~o)

Still not working, maybe some code might point out my trouble?



var wbForm2 = new Ext.FormPanel({
labelWidth: 90, // label settings here cascade unless overridden
frame: true,
bodyStyle:'padding:2px 2px 0',
defaultType: 'textfield'
});


var wbSelect2 = new Ext.form.ComboBox({
id: 'wbSelect2',
fieldLabel: 'Select a webBase ',
store: new Ext.data.SimpleStore ({
fields: ['wb', 'surname'],
data : [
['Cochrane', 'Cochrane'],
['Crawford', 'Crawford'],
['Forlong', 'Forlong'],
['Patterson', 'Patterson'],
['Wallace', 'Wallace']
]
}),
forceSelection: true,
displayField:'surname',
valueField: 'wb',
value: 'Cochrane', // New to Ext 2.0 Beta 1
// this sets the selected value on render.
emptyText:'Select a webBase:',
width: 180,
typeAhead: true,
mode: 'local',
triggerAction: 'all',
selectOnFocus:true
});


wbSelect2.on('select', function(e) {
dswbEvents.load({
params: { start: 0, limit: 20 }
});
});


dswbEvents.on('beforeload', function(dswbEvents, options) {
dswbEvents.baseParams = { // order 1
wb: wbSelect2.getValue()
};

filters.cleanParams(options.params); // order 2
var params = filters.buildQuery(filters.getFilterData());
Ext.apply(options.params, params);

// I tried reversing the order above, still does not make a difference?
});

dswbEvents.on('loadexception', function (){
alert('No Record found')
});

wbForm2.add(wbSelect2);
tbrHeader2.addField(wbForm2);
}
win.show();
}
});


I don't think I am translating your code correctly, since you are looking for a store to load into the combobox?

dswbEvents is the store of the grid panel, not the combobox.


There are no other onload calls for this store. Any more ideas?

cobnet
1 Nov 2007, 9:44 PM
There actually is no difference in all in the above coding and this:



dswbEvents.on('beforeload', function() {
// dswbEvents.on('beforeload', function(dswbEvents, options) {
dswbEvents.baseParams = { // order 1
wb: wbSelect2.getValue();
};

filters.getFilterData();
// filters.cleanParams(options.params); // order 2
// var params = filters.buildQuery(filters.getFilterData());
// Ext.apply(options.params, params);

// I tried reversing the order above, still does not make a difference?
});


Also if I comment out the filters.getFilterData(); line, still same result, no differences at all?
No errors either, ext must be finding everything, just not reporting the filter values?

hendricd
2 Nov 2007, 3:09 AM
@cobnet: I don't think you need to set any baseParams, just contribute your current CB values to the params (during the beforeload event chain).




theGrid.store.on('beforeload', function(dswbEvents, options) {
options.params || (options.params = {});
Ext.apply(options.params, {wb: wbSelect2.getValue() } );
});

GridFilter plugin has it's own beforeload event handler in place -- it will add the current filter values, you dont need to touch them.

tobi
2 Nov 2007, 9:16 AM
Hello,
I played with this excellent plugin, but for me it is not working properly
When I set a filter, it loads the grid, but do not send any filter data, but when I refresh the grid it sends now, and it sends always after that. What I miss?
I create the filter plugin like this (in the config of a gridPanel):



plugins: new Ext.ux.grid.GridFilters({filters:[
{type: 'string', dataIndex: 'title'},
{type: 'string', dataIndex: 'alias'},
{type: 'boolean', dataIndex: 'published'}
]})


Sorry about my English

ambience
2 Nov 2007, 11:32 AM
I can't really determine what order things are happening from that =) Can you show me the grid setup and when you first call .load on the data source?

cobnet
2 Nov 2007, 12:58 PM
@cobnet: I don't think you need to set any baseParams, just contribute your current CB values to the params (during the beforeload event chain).




theGrid.store.on('beforeload', function(dswbEvents, options) {
Ext.apply(options.params, {wb: wbSelect2.getValue() } );
});

GridFilter plugin has it's own beforeload event handler in place -- it will add the current filter values, you dont need to touch them.

Still does not work, I will get back to you on this one, I don't think the before on load event is firing on the initial load. Thanks for taking the time to point some things out about the filter I did not know though.

Mark

PS: This coding is live at: http://cobnet.com/icmsBeta2/wb.html. If you select the Search Events window, let it load, then simply select an option in the combo box you should see what I am talking about here.

olive38
4 Nov 2007, 11:15 PM
Thank you very much Ambience,
all is working like a charm for me now.
Bye,
Olive.

JeffHowden
6 Nov 2007, 4:16 PM
I'm running 2.0 RC1 and everytime I mouse over the filter menu and the system tries to render the 3 range menu items, it throws in error within Ext. Additionally, the value of the one field it is able to show is NaN with the error underline indicating a problem with the value. I've tried playing around with it in the hopes of fixing it, but am unable. See attached screenshot to see what I'm referring to.

Zyclops
6 Nov 2007, 7:00 PM
one field it is able to show is NaN with the error underline
I got the same error as jeff

ambience
7 Nov 2007, 6:18 AM
I have updated the EditableItem code so that it does not try to pass a value to the field if no initial value was provided (originally it was passing '' to the numeric fields). This appears to have fixed the invalid field problem. However, neither before or after the fix did only a single field render. Does the demo exhibit that behavior in your browsers?

hendricd
7 Nov 2007, 10:07 AM
@cobnet - I looked at your site sample, and this may cause an issue:




dswb.on('beforeload', function() {
dswb.baseParams = {
wb: wbSelect.getValue()
};
});

You cannot guarantee the ORDER in which any event will fire, and because of that, REsetting the baseParams in this fashion (within a beforeload handler) may not apply what you think, at the time you think it should. baseParams should really only be defined once for static params passed with every XHR request, not dynamic ones based on user input.

As I mentioned earlier, you should stick with something like this (for passing the current CB value in each request), without having to make any assumptions about when it might finally get called in the beforeload event 'chain':




dswb.on('beforeload', function(store, options) {
console.log(['beforeload', Ext.apply(options.params,{ wb: wbSelect.getValue()}) ]);


});

The previous should dump the current options.params (after that 'beforeload' event fires). What do see there?

Further, what does wbSelect.getValue() return (without the CB being touched at all) just before the first store load? Hint: It may not be returning a useable value -- yet?

JeffHowden
7 Nov 2007, 12:55 PM
I have updated the EditableItem code so that it does not try to pass a value to the field if no initial value was provided (originally it was passing '' to the numeric fields). This appears to have fixed the invalid field problem. However, neither before or after the fix did only a single field render. Does the demo exhibit that behavior in your browsers?

This change to EditableItem.js fixes the error for me. It was not occurring on your example which was running 2.0 Alpha1, so I suspect it's a change from Alpha1 to RC1 that was the problem.

Troy Wolf
7 Nov 2007, 2:30 PM
I am using this extension in a production grid, and loving it. Thanks!

My question is regarding the date filter. Currently, "Filters" expands to "Before", "After", and "On" which each bring up a calendar. I don't want the three options. I'd just like "Filters" to bring up the calendar to pick a day. Is this something that I can easily configure or am I left to extend this extension myself?

Thanks!

ambience
7 Nov 2007, 3:41 PM
Unfortunately it's no currently configurable in that way =\ But creating a custom filter to do this should be fairly strait forward.

Jeff: I've updated the demo code to RC1 which is why I asked if it was still dropping the last two fields for you (as I couldn't reproduce the issue in exactly the same way) =)

JeffHowden
7 Nov 2007, 6:53 PM
Jeff: I've updated the demo code to RC1 which is why I asked if it was still dropping the last two fields for you (as I couldn't reproduce the issue in exactly the same way) =)

Not only did my own copy begin to work once I updated the EditableItem.js file, but your online demo continued to work. I never experienced the problem in your online demo. (i.e., whatever it was was probably something that changed between Alpha1 and RC1.)

cobnet
7 Nov 2007, 8:57 PM
@cobnet - I looked at your site sample, and this may cause an issue:




dswb.on('beforeload', function() {
dswb.baseParams = {
wb: wbSelect.getValue()
};
});

You cannot guarantee the ORDER in which any event will fire, and because of that, REsetting the baseParams in this fashion (within a beforeload handler) may not apply what you think, at the time you think it should. baseParams should really only be defined once for static params passed with every XHR request, not dynamic ones based on user input.

As I mentioned earlier, you should stick with something like this (for passing the current CB value in each request), without having to make any assumptions about when it might finally get called in the beforeload event 'chain':




dswb.on('beforeload', function(store, options) {
console.log(['beforeload', Ext.apply(options.params,{ wb: wbSelect.getValue()}) ]);


});

The previous should dump the current options.params (after that 'beforeload' event fires). What do see there?

Further, what does wbSelect.getValue() return (without the CB being touched at all) just before the first store load? Hint: It may not be returning a useable value -- yet?

I tried your suggestions above, with no difference, I'll post details soon, in the mean time I found this in the Ext 2.0 docs for the ComboBox:


valueField : String
The underlying data value name to bind to this ComboBox (defaults to undefined if mode = 'remote' or 'value' if transforming a select) Note: use of a valueField requires the user to make a selection in order for a value to be mapped.


According to this, the value will never be mapped unless a selection is made. Kinda makes the value setting on the combo box useless?

I will reply to your above suggestions, still studying this thing abit.

reaper.br
8 Nov 2007, 5:17 AM
Thansk hendricd for the awnser earlier. But i also need to set the values for the others filter types, like date types. How can i do this?

Tks

hendricd
8 Nov 2007, 5:25 AM
From the Demo site (and the zip file's example):



var filters = new Ext.ux.grid.GridFilters({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'}
]});

reaper.br
8 Nov 2007, 5:59 AM
Sorry, I think I didn't explain it correctly. What I really need is to render the grid with the filter values set.


var filters = new Ext.ux.grid.GridFilters({filters:[ {type: 'numeric', dataIndex: 'id'},
{type: 'string', dataIndex: 'name', value: 'something'},
{type: 'numeric', dataIndex: 'price'},
{type: 'date', dataIndex: 'dateAdded'},
{type: 'list', dataIndex: 'size', options: ['extra small', 'small', 'medium', 'large', 'extra large'], phpMode: true, value: 'small' },
{type: 'boolean', dataIndex: 'visible'}
]});

For 2 two types of filter, I can set a value like that, but for the others i can't!
Actually, if you set value: false on the boolean filter, it won't add it to the filter collection.

I hope i made myself clear :)

hendricd
8 Nov 2007, 6:04 AM
Yes, for Booleans (a recent change a few days ago..):



var filters = new Ext.ux.grid.GridFilters({filters:[
{type: 'numeric', dataIndex: 'id'},
{type: 'string', dataIndex: 'name', value: 'something',active:true},
{type: 'numeric', dataIndex: 'price'},
{type: 'date', dataIndex: 'dateAdded'},
{type: 'list', dataIndex: 'size', options: ['extra small', 'small', 'medium', 'large', 'extra large'], phpMode: true, value: 'small' },
{type: 'boolean', dataIndex: 'visible',active:true,defaultValue:true}
]});

reaper.br
8 Nov 2007, 6:12 AM
and for the date and numeric types??

hendricd
8 Nov 2007, 6:26 AM
Dates: tricky, because (as written) there are three possible values to consider.

Numbers: same issue.


I now defer to Ambience ... ;)

hendricd
8 Nov 2007, 6:33 AM
Perhaps something like:



{type: 'numeric', dataIndex: 'price',value:{gt:40,lt:80}},
{type: 'date', dataIndex: 'dateAdded',value:{before:new Date('1/1/1980'),after:new Date('12/1/1979')}},

Troy Wolf
8 Nov 2007, 6:52 AM
I started a thread to get some help on a very related grid filtering topic, but I did not want to muddy up Ambience's thread. I do hope that Ambience will be able to shed some light on my question. :)

http://extjs.com/forum/showthread.php?t=17599

hendricd
8 Nov 2007, 9:31 AM
var filters = new Ext.ux.grid.GridFilters({filters:[ {type: 'numeric', dataIndex: 'id'},
{type: 'string', dataIndex: 'name', value: 'something'},
{type: 'numeric', dataIndex: 'price'},
{type: 'date', dataIndex: 'dateAdded'},
{type: 'list', dataIndex: 'size', options: ['extra small', 'small', 'medium', 'large', 'extra large'], phpMode: true, value: 'small' },
{type: 'boolean', dataIndex: 'visible'}
]});

//GridPanel constuctor:
......
,plugins: filters
,bbar: new Ext.PagingToolbar({
pageSize: this.options.pageSize,
store: this.store,
id:'pager',
plugins: filters,
displayInfo: true,
displayMsg: 'Displaying messages {0} - {1} of {2}',
emptyMsg: "No messages to display"
})

});

Also pass your existing GridFilters instance as a plugin for PagingToolbar.

chernomorez
8 Nov 2007, 12:04 PM
How easy would it be to extract all of the filters to a separate panel that could be placed at the tbar of the grid panel?


Thanks

Troy Wolf
8 Nov 2007, 12:08 PM
How easy would it be to extract all of the filters to a separate panel that could be placed at the tbar of the grid panel?
I don't know yet how easy, but I plan to find out because I want to build off this excellent extension to do what I describe in this thread:
http://extjs.com/forum/showthread.php?t=17599

Basically, I want a window (launched by a "filter" button in the tbar or bbar) where the user can apply filters.

hendricd
8 Nov 2007, 12:19 PM
I use the filterupdate event to trap filter selection changes as shown in this earlier post (http://extjs.com/forum/showthread.php?p=78550#post78550)
but you could do something similar with the new serialize event as well or override buildQuery too.

It all depends on your filter input/display desires.

olive38
9 Nov 2007, 5:27 AM
Hello Ambience,

sometimes I want to be able to filter a string column which is not sortable (because the cell value is a random aggregation of predifined values).

The problem is that the menu does not appear when the column is not sortable.

Do you think that you could something to keep the menu in this case ?

By the way (Jack do you read this ?) I think we would still want the menu to choose which column to display even if the column is not sortable, don't you agree ?

Olive

ambience
9 Nov 2007, 1:00 PM
olive: have you tried enableHdMenu: true on your grid panel?

JorisA
9 Nov 2007, 1:26 PM
Currently, the filters only work when I add a PagingToolbar. is that supposed to work like that? If so, why? Why not just hook to the grid's datastore?

And it would be cool to have a function to serialize and restore the column's state (so visibility, order and filters).

Furthermore this is how grid filtering is supposed to be :D

ambience
9 Nov 2007, 1:32 PM
Haha, no, that's not how they are supposed to work. I just did a quick test and removed the paging tool bar from the example. Filters still seemed to function.

Ext's tables DO remember visibility / order / sorting if you provide them with a stateId as well.

JorisA
9 Nov 2007, 2:28 PM
Hmm thats weird? I figured out where it goed wrong:


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

console.log("onbeforeloooad", options, params);
},


If I leave out that red line, the options object does not have any properties after the apply call. If I add it it submits the filters as expected :-S

hendricd
9 Nov 2007, 2:39 PM
Yes, that would make sense, since GridFilter's 'beforeload' event MIGHT be the first of many called, so it would need to ensure options.params was not undefined, causing Ext.apply to fail:




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

console.log("onbeforeloooad", options, params);
},



Nice catch JorisA !

ambience
9 Nov 2007, 2:56 PM
Updated, good catch. I didn't remove the paging parameters from my store.load() call during the test >.<

cobnet
10 Nov 2007, 11:43 AM
Yes, that would make sense, since GridFilter's 'beforeload' event MIGHT be the first of many called, so it would need to ensure options.params was not undefined, causing Ext.apply to fail:




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

console.log("onbeforeloooad", options, params);
},



Nice catch JorisA !

This fixed my problem as well! I ended up with:



dswbEvents.on('beforeload', function(dswbEvents, options) {
options.params || (options.params = {});
Ext.apply(options.params, {wb: wbSelect2.getValue() } );
console.log("onbeforeload", options.params);
});


The 2 lines:
"this.cleanParams(options.params);
var params = this.buildQuery(this.getFilterData());"
comes back with this.cleanParams is not a function and this.getFilterData is not a function?

Anyways, it is working now on the first load,
Thanks,
Mark

EDITED:
I download the latest filter scripts and it is filtering on the intial load now! Great, now I cannot seem to get the start and limit params to work?



var dswb = new Ext.data.JsonStore({
url: 'edited-myurl',
root: 'mywb',
id: 'mainid',
totalProperty: 'totalCount',
remoteSort: true,
sortInfo : {field: 'fname', direction: 'ASC'},
params: {start: 0, limit: 20},
autoLoad: true,
successProperty: 'success',
fields: ['mainid', 'treeid', 'parentsid', 'prefix', 'fname', 'mname', 'surname', 'suffix', 'aka', 'gender', 'date']
});

dswb.on('beforeload', function(dswb, options) {
options.params || (options.params = {});
// this.cleanParams(options.params); // this.cleanParams is not a function?
// var params = this.buildQuery(this.getFilterData()); // this.getFilterData is not a function?
Ext.apply(options.params, {wb: wbSelect.getValue() } );
// console.log("onbeforeload", options.params); // IE does not like this.
});

dswb.on('loadexception', function () {
alert('Load Exception: Probably means no matches were found for a webBase search.')
});

Now it works like it should except for the paging toolbar shows "NaN", where am I going wrong here?
Thanks in advance,
Mark

hermeslm
10 Nov 2007, 8:59 PM
Hi all

I started using this wonderful plugin. Based on the example I made my code, but though
showed filter on column headers, the calls it generated never had all filtered params.

I did NOT use pagin bottom bar

After a LOT a tries I add the load the literal object with a params property just like if it were using paging, and It made the ajax call perfectly well, I even just placed an empy


{params : {}}

any special reazon for that??

I using it that way no problem, but IMHO would be may better without that detail

thanks

Chelala

ambience
11 Nov 2007, 8:25 AM
hermeslm: I've posted an example without the paging tool bar at http://ccinct.com/lab/filter-grid/noPb.html and it appears to work with out passing any options to the load function. Can you post an example that exhibits the behavior you described some where?

cobnet: I am not sure you are allowed to pass 'params' as a configuration option to the store. Are you sure you do not mean to be passing the baseParams option?

reaper.br
12 Nov 2007, 3:56 AM
@Ambience: I've made a question earlier in this thread (http://extjs.com/forum/showthread.php?p=83899#post83899) but no one can awnser this but you!

How can I set a initial value for the numeric and the date filter types?? :-?

btw, thanks for this excelent plugin! =D>

ambience
12 Nov 2007, 5:55 AM
hendricd was correct when he suggested passing an object of values as the value parameter


Date:
{type: 'date', value: {on: '1/1/2007'}, ...}
{type: 'date', value: {after: '1/1/2007', before: '1/10/2007'}, ...}

Numeric:
{type: 'date', value: {eq: 42}, ...}
{type: 'date', value: {gt: 0, lt: 3.14159265}, ...}


If this is not working correctly, then it is a bug and I need to fix it =) Have you tried it?

hendricd
12 Nov 2007, 6:00 AM
@Ambience: those were strictly future implementation recommendations :">. I do not believe the filters are currently coded to handle default values in this manor.

ambience
12 Nov 2007, 6:04 AM
They are actually =) value simply calls this.setValue(value); this.setActive(true); and the setValue function is defined for both types.

hendricd
12 Nov 2007, 6:20 AM
By George! Your right. It does work that way!

What a lucky guess on my part ;)

I only wish that during filter construction we could do:

{type: 'numeric', dataIndex: 'number', value:{gt:40},active:false},

that is -- have it still set the filter's subvalue, yet honor the active=false (which setValue always sets to true).

ambience
12 Nov 2007, 6:22 AM
Good call, I'll make the modification and post it with the next bug fix round.

hendricd
12 Nov 2007, 6:26 AM
if(config && config.value){
this.setValue(config.value);
this.setActive(config.active||false , true); //or equiv
delete config.value;
}

for Ext.ux.grid.filter.Filter ?

But that still creates a problem for DateFilter, (active=true for Subfilter (before, after, on ) , hmm...

hendricd
12 Nov 2007, 6:30 AM
See revised previous post

ambience
12 Nov 2007, 6:56 AM
this.setActive(config.active!==false, true);

As I would like the default action to be activation of filters with value provided. I am unclear as to what problem with date filters you are speaking of.

hendricd
12 Nov 2007, 7:09 AM
DateFilter, is the only one (I think) that support second-level filter checkboxes. So, something like this:




{type: 'date', value: {after: {value: new Date('1/1/2007'),active:true},
before: {value:new Date('1/10/2007'),active:false}
}
}

reaper.br
12 Nov 2007, 7:29 AM
For the numeric values it works OK, but for the date i get the following error


value.clearTime is not a function
http://localhost/include/extjs/ext-all-debug.js
Line 18206

Here's my call:

{ type: 'date', dataIndex: 'Data', dateFormat: 'd/m/Y', value: {before: '1/1/2007'} }

Note that I use a diff dateFormat, but, even taking that out, the error is the same.

Thanks

ambience
12 Nov 2007, 7:35 AM
Reaper: A full stack trace would be super helpful. I don't have much time durring the day to play with test cases =)

Doug: I'll see about adding the non-activating default values to the more complex fields.

olive38
12 Nov 2007, 7:36 AM
olive: have you tried enableHdMenu: true on your grid panel?

Yes but the menu does not display anyway if 'sortable' is false.

hendricd
12 Nov 2007, 7:53 AM
@Reaper.br: Try this one:



{ type: 'date', dataIndex: 'Data', dateFormat: 'd/m/Y', value: {before: new Date('1/1/2007') } }

hendricd
12 Nov 2007, 8:15 AM
For those who have started setting default values for filters, the following may be necessary for situations where the grid has never been loaded yet when the filters become active for the first time:



Ext.override(Ext.ux.grid.GridFilters,{
/** private **/
reload: function(){
if(this.local){
this.grid.store.clearFilter(true);
this.grid.store.filterBy(this.getRecordFilter());
} else {
var store = this.grid.store;
if(this.toolbar){
var start = this.toolbar.paramNames.start;
store.lastOptions || (store.lastOptions = {params : {}});
if(store.lastOptions.params[start])
store.lastOptions.params[start] = 0;
}

store.reload();
}
}
});



EDIT: This fix is now part of the distribution.

reaper.br
12 Nov 2007, 8:55 AM
hendricd: That worked, thankss!!! But the date format returned is US (m/d/y), even if i put in the config the dateFormat: 'd/m/Y', that doesn't work.

I also tried prototyping the dateFilter dateFormat


Ext.ux.grid.filter.DateFilter.prototype.dateFormat = 'd/m/Y';

I tried tracing where the date gets the US format, but I had no luck =/
Maybe i'm looking at the wrong places :((.

What is the initial event that I can get my filter value?

Thanks for all :)

hendricd
12 Nov 2007, 9:23 AM
Then you'll likely need something like:

{ type: 'date', dataIndex: 'Data', dateFormat: 'd/m/Y', value: {before: Date.parseDate('31/01/2007','d/m/Y') } }

reaper.br
12 Nov 2007, 9:36 AM
Yeah! Thats it \:D/

I didn't know how to properly format the date value..

Thanks for all =)

hendricd
12 Nov 2007, 9:37 AM
See previous post revised ;) (cleaner version - returns Date object you need )

cobnet
12 Nov 2007, 10:38 AM
cobnet: I am not sure you are allowed to pass 'params' as a configuration option to the store. Are you sure you do not mean to be passing the baseParams option?

You are correct, however using baseParams will send the same start: 0, limit: 20 on every call, thus making the pagingToolbar useless. I was able to get this to work like so thou:



var dswb = new Ext.data.JsonStore({
url: 'http://cobnet.com/modx/096/assets/templates/webBase/wb.php',
root: 'mywb',
id: 'mainid',
totalProperty: 'totalCount',
remoteSort: true,
sortInfo : {field: 'fname', direction: 'ASC'},
autoLoad: true,
successProperty: 'success',
fields: ['mainid', 'treeid', 'parentsid', 'prefix', 'fname', 'mname', 'surname', 'suffix', 'aka', 'gender', 'date']
});

dswb.on('beforeload', function(dswb, options) {
options.params || (options.params = {start: 0, limit: 20});
// this.cleanParams(options.params); // this.cleanParams is not a function?
// var params = this.buildQuery(this.getFilterData()); // this.getFilterData is not a function?
Ext.apply(options.params, {wb: wbSelect.getValue() } );
// console.log("onbeforeload", options.params); // IE does not like this.
});


The way I read the on beforeload call is:

If (options.params || set the start and limit settings), on the initial load, the params (start and limit) should be set, so it should ignore the start and limit settings on each call after that.

Anyways, I do appreciate your (hendricd and ambience) time in helping me solve this problem. All is working correctly now!
Mark

ericwaldheim
12 Nov 2007, 6:21 PM
I'd like to see Ext.ux.grid.GridFilters.reload cancel deferredUpdates.
Right?
Thanks,
Eric

(And thanks for the filters. Amazing.)

lupin85.luca
14 Nov 2007, 8:32 AM
Hi all.

I can't figure out how to display which filter has been applied to a column.
Example:
I filter the 'Surname' col with the string 'findme'.
What I want, is to be able to display the condition of this operation in a logger console.
Such as: logger.debug(ColumnFiltered, Condition(in this case would be '='), ValueOfTheFilter).
So, in the logger, I'd see: 'Surname', ' = ', 'findme'.

Could anyone help me?

Thanks and sorry for bad english.

hendricd
14 Nov 2007, 8:41 AM
grid.filters.getState() should get you in right direction. It returns an object(hash) of all currently active filters and on what column.

kesteb
15 Nov 2007, 1:47 PM
Nice extension.

But here is a little problem. I am loading the filter options from the server. There are a total of 58 items. They will not all fit within the browsers window and the filter box doesn't scroll. So all the items can not be displayed.

So it would be nice if the box would scroll.

ambience
15 Nov 2007, 4:36 PM
Yeah, I asked the Ext team about support for scrolling menus and they said not in this version >.<

hendricd
15 Nov 2007, 4:41 PM
Scrolling menus are a rare find, and 58 menu items seems a bit atypical, no ?.

JeffHowden
15 Nov 2007, 4:45 PM
Scrolling menus are a rare find, and 58 menu items seems a bit atypical, no ?.

I'd have to second that. As a user, I think I'd probably shoot myself if I went to filter a column and discovered a list menu with 58 checkboxed items. I'd much rather just type what I'm looking for in a text box.

kesteb
16 Nov 2007, 8:21 AM
You make a good point. So I reverted the code. I was rather cool that I could load the options from the server thou.

Thanks for the suggestion.

kesteb
16 Nov 2007, 8:47 AM
Ok, anybody else feel that the parsing of the filter parameters to be real annoying. It would be so much easier if the filter names were column name = value. With the 3 options of the date filter having "after=<date>". "before=<date>" and "datetime=<date>".

hendricd
16 Nov 2007, 9:05 AM
The most common appraoch is to override the buildQuery method and reconstruct the params as you see fit. The GridFilters.getState method also returns a object(hash) of currently active filter values which may help you out further.

kesteb
16 Nov 2007, 1:53 PM
Is there an example on how to override buildQuery?

hendricd
16 Nov 2007, 2:03 PM
By the instance:


grid.filters.buildQuery = function(filters){
var p = {};
for(var i=0, len=filters.length; i<len; i++){
var f = filters[i];
//modify to suite your needs
}

return p; //a flattened params object
},

For all instances:


Ext.override( Ext.ux.grid.GridFilters ,{
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; //a flattened params object
}
});

paliwalg
19 Nov 2007, 6:12 AM
Hi,

Can you please share the js code to create the above filter with all the filter columns under one hierarchy and grid being used to select the filter values.

Thanks

hendricd
19 Nov 2007, 6:29 AM
@paliwalg - which ' above filter' ? What are trying to do ?

robasi
19 Nov 2007, 3:01 PM
Liking this plugin a lot. I searched the thread for "Sensitive" and got no hits. Is there a way to have the filters ignore case when searching?

hendricd
19 Nov 2007, 4:59 PM
Isn't that up to either:

a) your serverside query, or
b) your clientside filtering function ?

paliwalg
20 Nov 2007, 2:06 AM
Ambience,

Can you please share the js code to create the filter with all the filter columns under one hierarchy and grid being used to select the filter values (its wrt to the post on page 2).

Thanks

crxtech
20 Nov 2007, 8:24 AM
Has anyone used this filter with coldfusion?
If so could you post an example of how to access the filter variables for the queries? I have the filters all setup and they look great, they just don't do anything yet because I'm new at this and don't know how to access the filters for my queries.

Thanks,

ambience
20 Nov 2007, 9:11 AM
robasi: Doug is correct, that is a limitation in the current local filters. I'll address this in the next update.

paliwalg: Those filters are still in the pre-alpha filter architecture and have not been brought forward as of yet. For compound filter menu examples, you can look at the source code for the date filters. The trees were loosely based off of Ext's combo-box code.

JeffHowden
20 Nov 2007, 10:32 AM
Has anyone used this filter with coldfusion?
If so could you post an example of how to access the filter variables for the queries? I have the filters all setup and they look great, they just don't do anything yet because I'm new at this and don't know how to access the filters for my queries.

I'm using it with ColdFusion, but it required overriding the buildQuery() method to send "cleaner" name/value pairs to the server.


Ext.override(Ext.ux.grid.GridFilters, {
buildQuery: function(filters) {
var p = {};
var filterlist = [];
var field, type, comparison, value;
for(var i = 0, len = filters.length; i < len; i++) {
field = filters[i].field;
type = filters[i].data.type;
comparison = null;
if(filters[i].data.comparison)
comparison = filters[i].data.comparison;
value = filters[i].data.value || '';
p[field + '_type'] = type;
if(!comparison)
p[field + '_value'] = value;
else
p[field + '_' + comparison] = value;
if(filterlist.indexOf(field) == -1)
filterlist.push(field);
}
filterlist = filterlist.join(',');
p.filters = filterlist;
return p;
}
});

crxtech
20 Nov 2007, 1:04 PM
Thanks for your fast response, but how do I access the filter variables to pass them to my stored proc? Here is what I have so far, I just don't know how to pass the filters into the query...

index.cfm

<html>
<head>
<script type="text/javascript" src="ext-base.js"></script>
<script type="text/javascript" src="ext-all.js"></script>

<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>

<script type="text/javascript">
Ext.onReady(function(){
Ext.ux.menu.RangeMenu.prototype.icons = {
gt: 'images/greater_then.png',
lt: 'images/less_then.png',
eq: 'images/equals.png'
};
Ext.ux.grid.filter.StringFilter.prototype.icon = 'images/find.png';


var ds = new Ext.data.GroupingStore({
proxy: new Ext.data.HttpProxy({
url:'gridXML.cfm'
}),

reader: new Ext.data.XmlReader({
totalRecords: "totalProjects",
record: "project",
}, Ext.data.Record.create([
{name:'region'},
{name:'SUBMITED_COUNTRY'},
{name:'PROJECT_NUMBER'},
{name:'PROJECT_TITLE'},
{name:'PROJECT_SDATE'},
{name:'PROJECT_EDATE'},
{name:'SUBMITED'},
{name:'DOWNLOADED'},
{name:'APPROVED'},
{name:'SYSDATE'},
{name:'Project_File'},
{name:'STATUS'},
{name:'C_R_TYPE'}])),

groupField: 'region',
sortInfo: {field: 'SUBMITED_COUNTRY', direction: 'ASC'},
remoteSort: false
});

var filters = new Ext.ux.grid.GridFilters({filters:[
{type: 'string', dataIndex: 'SUBMITED_COUNTRY'},
{type: 'numeric', dataIndex: 'PROJECT_NUMBER'},
{type: 'string', dataIndex: 'PROJECT_TITLE'},
{type: 'date', dataIndex: 'PROJECT_SDATE'},
{type: 'date', dataIndex: 'PROJECT_EDATE'},
{type: 'date', dataIndex: 'SUBMITED'},
{type: 'date', dataIndex: 'DOWNLOADED'},
{type: 'date', dataIndex: 'APPROVED'},
{type: 'date', dataIndex: 'SYSDATE'},
{
type: 'list',
dataIndex: 'region',
options: ['CARO', 'SARO', 'EARO', 'SEAPRO', 'South East Asia', 'WARO'],
phpMode: false
},
{type: 'boolean', dataIndex: 'Project_File'}
]});

Ext.override(Ext.ux.grid.GridFilters, {
buildQuery: function(filters) {
var p = {};
var filterlist = [];
var field, type, comparison, value;
for(var i = 0, len = filters.length; i < len; i++) {
field = filters[i].field;
type = filters[i].data.type;
comparison = null;
if(filters[i].data.comparison)
comparison = filters[i].data.comparison;
value = filters[i].data.value || '';
p[field + '_type'] = type;
if(!comparison)
p[field + '_value'] = value;
else
p[field + '_' + comparison] = value;
if(filterlist.indexOf(field) == -1)
filterlist.push(field);
}
filterlist = filterlist.join(',');
p.filters = filterlist;
return p;
}
});

var cm = new Ext.grid.ColumnModel([{
dataIndex: 'region',
header: 'Region', width: 75
}, {
dataIndex: 'SUBMITED_COUNTRY',
header: 'Submited By', width: 85
}, {
dataIndex: 'PROJECT_NUMBER',
header: 'Project number', width: 80
}, {
dataIndex: 'PROJECT_TITLE',
header: 'Project Title', width: 150
}, {
dataIndex: 'PROJECT_SDATE',
header: 'Start Date', width: 65
}, {
dataIndex: 'PROJECT_EDATE',
header: 'End Date', width: 65
}, {
dataIndex: 'SUBMITED',
header: 'Submited', width: 65
}, {
dataIndex: 'DOWNLOADED',
header: 'Downloaded', width: 70
}, {
dataIndex: 'APPROVED',
header: 'Approved', width: 65
}, {
dataIndex: 'SYSDATE',
header: 'Updated', width: 65
}, {
dataIndex: 'Project_File',
header: 'Project File', width: 65
}, {
dataIndex: 'STATUS',
header: 'Status', width: 75
}, {
dataIndex: 'C_R_TYPE',
header: 'C/R', width: 25
}]);
cm.defaultSortable = true;

var grid = new Ext.grid.GridPanel({
id: 'example',
ds: ds,
cm: cm,
enableColLock: false,
loadMask: true,
view: new Ext.grid.GroupingView(),
plugins: filters,
height:400,
width:1000,

el: 'grid-example',

bbar: new Ext.PagingToolbar({
store: ds,
pageSize: 15,
plugins: filters
})
});
grid.render();

ds.load({params:{start: 0, limit: 15}});
});
</script>

<style type="text/css" title="currentStyle" media="screen">
@import "ext-all.css";

.x-grid3-hd-row td.ux-filtered-column {
font-style: italic;
font-weight: bold;
}
</style>
</head>

<body>
<h1 align="center">Project Submission Status Report</h1>
<div id="grid-example" style="margin: 10px;"></div>
</body>
</html>

gridXML.cfm

<CFSTOREDPROC procedure="dbo.sp_PTS_Project_Status" datasource="PTS_DATA_PROD">
<CFPROCRESULT name="get_Projects">
</CFSTOREDPROC>

<cfcache action="flush" expireurl="*/gridXML.cfm*">
<cfparam name="FORM.start" default="1">
<cfparam name="FORM.limit" default="15">
<cfif FORM.start IS 0><cfset FORM.start = 1></cfif>
<cfcontent type="text/xml">
<cfsetting enablecfoutputonly="no" showdebugoutput="no">
<cfxml variable="portalProjects">
<?xml version='1.0' encoding='utf-8' ?>
<portalProjects>
<totalProjects><cfoutput>#get_Projects.recordcount#</cfoutput></totalProjects>
<cfoutput query="get_Projects" startrow="#FORM.start#" maxrows="#FORM.limit#">
<project>
<region>#XMLformat(Region)#</region>
<SUBMITED_COUNTRY>#XMLformat(SUBMITED_COUNTRY)#</SUBMITED_COUNTRY>
<PROJECT_NUMBER>#XMLformat(PROJECT_NUMBER)#</PROJECT_NUMBER>
<PROJECT_TITLE>#XMLformat(PROJECT_TITLE)#</PROJECT_TITLE>
<PROJECT_SDATE>#DateFormat(PROJECT_SDATE, 'mm/dd/yyyy')#</PROJECT_SDATE>
<PROJECT_EDATE>#DateFormat(PROJECT_EDATE, 'mm/dd/yyyy')#</PROJECT_EDATE>
<SUBMITED>#DateFormat(SUBMITED, 'mm/dd/yyyy')#</SUBMITED>
<DOWNLOADED>#DateFormat(DOWNLOADED, 'mm/dd/yyyy')#</DOWNLOADED>
<APPROVED>#DateFormat(APPROVED, 'mm/dd/yyyy')#</APPROVED>
<SYSDATE>#DateFormat(SYSDATE, 'mm/dd/yyyy')#</SYSDATE>
<Project_File>#XMLformat(Project_File)#</Project_File>
<STATUS>#XMLformat(STATUS)#</STATUS>
<C_R_TYPE>#XMLformat(C_R_TYPE)#</C_R_TYPE>
</project>
</cfoutput>
</portalProjects>
</cfxml>

<cfoutput>#portalProjects#</cfoutput>

kesteb
20 Nov 2007, 2:42 PM
By the instance:


grid.filters.buildQuery = function(filters){
var p = {};
for(var i=0, len=filters.length; i<len; i++){
var f = filters[i];
//modify to suite your needs
}

return p; //a flattened params object
},

For all instances:


Ext.override( Ext.ux.grid.GridFilters ,{
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; //a flattened params object
}
});


Thanks, this is the solution that I came up with:

Overide buildQuery() as follows:



Ext.override( Ext.ux.grid.GridFilters , {
buildQuery : function(filters) {
var p = {};

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

var f = filters[i];

if (f.data.type == 'date') {
if (f.data.comparison == 'gt') {
p['after'] = f.data.value;
} else if (f.data.comparison == 'lt') {
p['before'] = f.data.value;
} else if (f.data.comparison == 'eq') {
p['datetime'] = f.data.value;
}
} else {
p[f.field] = f.data.value;
}

}

return p;

}

});


Which leads to the problem of parameters not being removed from options.params. So the following code handles that:



Ext.override( Ext.ux.grid.GridFilters , {
cleanParams : function(p) {
var params = this.paramPrefix.split(',');

for (var i = 0, len = params.length; i < len; i++) {

var regex = new RegExp('^' + params[i]);
for (var key in p) {

if (regex.test(key)) {

delete p[key];

}

}

}
}

});




This code allows "paramPrefix" to be a comma separated list of values to check for. There is probably a better way of handling this, but it works for me.

hendricd
20 Nov 2007, 3:02 PM
To support date ranges (and more than one date field) your might need a little more flex:



Ext.override( Ext.ux.grid.GridFilters , {
buildQuery : function(filters) {
var p = {};

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

var f = filters[i];

var root = [this.paramPrefix,'-', f.data.type , '-', f.field].join('');

if (f.data.type == 'date') {

if (f.data.comparison == 'gt') {
p[root+'-after'] = f.data.value; //yields:{filter-date-invoicedate-after:value}
}
if (f.data.comparison == 'lt') {
p[root+'-before'] = f.data.value;
}
if (f.data.comparison == 'eq') {
p[root+'-datetime'] = f.data.value;
}
} else {
p[root] = f.data.value;
}
if(f.data.format){
p[ [this.paramPrefix,'-',f.data.type,'-format'].join('') ]= f.data.format;
}

}

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 + "-"); //loose but adequate
for(var key in p)
if(regex.test(key))
delete p[key];
}

});
Downside is though:
The longer the param names are, the more likely you'll have to use POST just to get them to the server ;)

JeffHowden
20 Nov 2007, 5:17 PM
Thanks for your fast response, but how do I access the filter variables to pass them to my stored proc? Here is what I have so far, I just don't know how to pass the filters into the query...

Use firebug to inspect what is being sent to the server and how (form or url).

peio72
22 Nov 2007, 8:55 AM
I have created a grid:



/*
* Ext JS Library 2.0 RC 1
* Copyright(c) 2006-2007, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/

Ext.onReady(function(){
Ext.ux.menu.RangeMenu.prototype.icons = {
gt: '../img/greater_then.png',
lt: '../img/less_then.png',
eq: '../img/equals.png'
};
Ext.ux.grid.filter.StringFilter.prototype.icon = '../img/find.png';


var ds = new Ext.data.GroupingStore({
proxy: new Ext.data.HttpProxy({
url:'../actions/in_consult.xml',
method:'GET'
}),

reader: new Ext.data.XmlReader({
record: "Expert"
}, Ext.data.Record.create([
{name:'ID'},
{name:'Name'},
{name:'Fname'},
{name:'Country'},
{name:'Gender'},
{name:'Explist'},
{name:'Expkeyw'},
{name:'Affiliation'},
{name:'Itasks'},
{name:'Status'}])),


sortInfo: {field: 'ID', direction: 'ASC'},
remoteSort: true
});

var filters = new Ext.ux.grid.GridFilters({filters:[
{type: 'numeric', dataIndex: 'ID'},
{type: 'string', dataIndex: 'Name'},
{type: 'string', dataIndex: 'Fname'},
{type: 'string', dataIndex: 'Country'},
{
type: 'list',
dataIndex: 'Gender',
options: ['M','F'],
phpMode: false
},
{
type: 'list',
dataIndex: 'Explist',
options: ['Keyword1', 'Keyword2', 'Keyword3', 'Keyword4', 'Keyword5'],
phpMode: false
},
{
type: 'list',
dataIndex: 'Expkeyw',
options: ['Keyword1', 'Keyword2', 'Keyword3', 'Keyword4', 'Keyword5'],
phpMode: false
},
{
type: 'list',
dataIndex: 'Status',
options: ['New', 'Validated','Updated', 'Selected', 'Rejected'],
phpMode: false
}
]});

Ext.override(Ext.ux.grid.GridFilters, {
buildQuery: function(filters) {
var p = {};
var filterlist = [];
var field, type, comparison, value;
for(var i = 0, len = filters.length; i < len; i++) {
field = filters[i].field;
type = filters[i].data.type;
comparison = null;
if(filters[i].data.comparison)
comparison = filters[i].data.comparison;
value = filters[i].data.value || '';
p[field + '_type'] = type;
if(!comparison)
p[field + '_value'] = value;
else
p[field + '_' + comparison] = value;
if(filterlist.indexOf(field) == -1)
filterlist.push(field);
}
filterlist = filterlist.join(',');
p.filters = filterlist;
return p;
}
});

var cm = new Ext.grid.ColumnModel([{
dataIndex: 'ID',
header: 'ID', width: 50
}, {
dataIndex: 'Name',
header: 'Name', width: 100
}, {
dataIndex: 'Fname',
header: 'First Name', width: 80
}, {
dataIndex: 'Country',
header: 'Country', width: 60
}, {
dataIndex: 'Gender',
header: 'Gender', width: 60
}, {
dataIndex: 'Explist',
header: 'Experience(list)', width: 200
}, {
dataIndex: 'Expkeyw',
header: 'Experience(keywords)', width: 200
}, {
dataIndex: 'Affiliation',
header: 'Affiliation', width: 80
}, {
dataIndex: 'Itasks',
header: 'Involved tasks', width: 150
}, {
dataIndex: 'Status',
header: 'Status', width: 65
}]);
cm.defaultSortable = true;

var grid = new Ext.grid.GridPanel({
id: 'example',
ds: ds,
cm: cm,
enableColLock: false,
loadMask: true,
view: new Ext.grid.GroupingView(),
plugins: filters,

el: 'grid-example',


viewConfig: {
forceFit:true
},

// inline toolbars
tbar:[{
text:'Export PDF',
iconCls:'pdf',
handler : function(){
window.open('get_pdf?'+ds.params);

}
}, '-', {
text:'Export Excel',
iconCls:'excel'
}],

height:300,
width:1070,
frame:true,
title:'List of Experts',
iconCls:'icon-grid'


});
grid.render();

ds.load();



});


in it I added a button:


// inline toolbars
tbar:[{
text:'Export PDF',
iconCls:'pdf',
handler : function(){
window.open('get_pdf?'+ds.params);

I would like to get the same parameters which are sent to the
url:'../actions/in_consult.xml' and send them to an external url by clicking on a button to create a pdf using those same parameters.

What should this line be to get the same parameters ?


window.open('get_pdf?'+ds.params);

Thanx for your help.

hendricd
22 Nov 2007, 9:02 AM
window.open('get_pdf?'+Ext.urlEncode(grid.filters.buildQuery(grid.filters.getFilterData() ) );

peio72
23 Nov 2007, 12:55 AM
I'm sorry, it's not working ...

Someone has another solution ?

Thanx.

peio72
23 Nov 2007, 2:56 AM
I'm sorry it's working , (I just forgot to select some filters)

There is stille just one issue remaining regarding the remote sort.

How to add the sort parameters ?

sort=ID&dir=ASC

?

Thanx a lot.

hendricd
23 Nov 2007, 6:27 AM
var gs=grid.store,sorts={};

if(gs.sortInfo && gs.remoteSort){
var pn = gs.paramNames;
sorts[pn["sort"]] = gs.sortInfo.field;
sorts[pn["dir"]] = gs.sortInfo.direction;
}

window.open('get_pdf?'+
Ext.urlEncode(
Ext.apply(
grid.filters.buildQuery(grid.filters.getFilterData() )
,sorts)
) );

mjlecomte
26 Nov 2007, 6:00 PM
Thanks for sharing this!

Please forgive a basic question, I'm still a beginner. I made the following observations playing around with this plugin, maybe the problems cited below are my errors and not limitations of the plugin.

Example 1 is ok:


filters = new Ext.ux.grid.GridFilter({
filters:[
{dataIndex: 'index1', type = ...},
{dataIndex: 'index2', type = ...},
{dataIndex: 'index3', type = ...},
{dataIndex: 'index4', type = ...},
{dataIndex: 'index5', type = ...},//no match in grid, but ok
]
});

colModel = new Ext.grid.ColumnModel([

{dataIndex: 'index1', ...},
{dataIndex: 'index2', ...},
{dataIndex: 'index3', ...},
{dataIndex: 'index4', ...},

]);


Example 2 is no good:


filters = new Ext.ux.grid.GridFilter({
filters:[
{dataIndex: 'index1', type = ...},
{dataIndex: 'index2', type = ...},
{dataIndex: 'index3', type = ...},
// {dataIndex: 'index4', type = ...},//if this is missing no filters show

]
});

colModel = new Ext.grid.ColumnModel([

{dataIndex: 'index1', ...},
{dataIndex: 'index2', ...},
{dataIndex: 'index3', ...},
{dataIndex: 'index4', ...}

]);


Questions:
1. Example 1 doesn't blow up, which is nice. Example 2 blows up basically. If possible, maybe there can be some default set such that it won't blow up?
2. Even more preferable option to question 1, would be the ability to NOT specify filters on certain rows? If so, how? I tried type: '' but that didn't work. Regardless, have it default to no filter on that column in lieu of blowing up?
3. I'm very green, I don't really understand the difference between extending and a plugin. Looking at the above examples and my questions I would think it would be better if there was a way to forget specifying filter separately and specify the filtering in the column model as shown in the example below. Maybe this is so this plugin can be used for other widgets?



colModel = new Ext.grid.ColumnModel([

{dataIndex: 'index1', filter:{type: 'string', value: 'something'}, ...},
{dataIndex: 'index2', ...}, //no filter this column
{dataIndex: 'index3', filter:{type: 'string', value: 'something'}, ...},
{dataIndex: 'index4', filter:{type: 'string', value: 'something'}, ...}

]);

pic_Nick
27 Nov 2007, 3:48 AM
Hello ambience! It's a very-very cool plugin :) But, can you add localization support to the next version, so it will be even better?
Thanks in advance.

catof
27 Nov 2007, 3:52 AM
how can i modify the value of a filter from a button?



//before this the definition of the Paging toolbar
{
type: 'button',
text: 'Load filter',
cls: 'x-btn-text-icon details',
handler: function () {
tmpfilters = grid.filters.getFilterData()
grid.filters.filters[1].value = 'test';
}

But don't work....

nonamebrand
27 Nov 2007, 5:11 AM
Example 2 is no good:
....
{dataIndex: 'index3', type = ...},
// {dataIndex: 'index4', type = ...},//if this is missing no filters show
]
});
....


If you are using IE, becareful of the extra comma ... you have an extra comma at the end of the line {dataIndex: 'index3', type = ...}, and the array is closed thereafter, in IE this will cause a syntax error and things won't work, FF will ignore it.

hendricd
27 Nov 2007, 7:42 AM
how can i modify the value of a filter from a button?

The filter has an API for all that:


//before this the definition of the Paging toolbar
{
type: 'button',
text: 'Load filter',
cls: 'x-btn-text-icon details',
handler: function () {
var filter = grid.filters.getFilter('color');
filter.setValue ('blue');
filter.setActive(true);
}
}

catof
27 Nov 2007, 9:20 AM
The filter has an API for all that:


//before this the definition of the Paging toolbar
{
type: 'button',
text: 'Load filter',
cls: 'x-btn-text-icon details',
handler: function () {
var filter = grid.filters.getFilter('color');
filter.setValue ('blue');
filter.setActive(true);
}
}

Thanks hendricd ... it's works but i have another question...
It's works only with string filter ... i have tried with a numeric (or list and date ) and i don't find a solution

This is my code


var filter = grid.filters.getFilter('Id');
filter.setValue ('eq:1');
filter.setActive(true);
( tried also with '{eq:1}' )

hendricd
27 Nov 2007, 9:24 AM
You'll have to examine the setValue method of each filter type and figure out what each one expects. As you pointed out, some have mulitple qualifiers. ;)

Dates example: setValue({before: somedate, after: otherdate, on: new Date()});
Number: setValue({eq:10});
Boolean : setValue(true);
List: setValue(['Green','Brown','black']);

catof
27 Nov 2007, 9:43 AM
The numeric filter works without the '


var filter = grid.filters.getFilter('Id');
filter.setValue ({eq:1});
filter.setActive(true);


Thanks again;)

ReyBango
27 Nov 2007, 1:54 PM
Thanks for the plugin guys:

Ext JS Blog:
http://extjs.com/blog/2007/11/26/extended-filtering-using-the-grid-filter-plugin/

Ajaxian:
http://ajaxian.com/archives/new-grid-filter-plugin-for-ext

Rey

boyjunqiang
28 Nov 2007, 12:50 AM
ambience, can you give some code to tell how can you do this
http://picasaweb.google.com/boyjunqiang/VFmYgC/photo#5137809191119357938
I try do this all day , :salmost give up :(

chernomorez
28 Nov 2007, 8:40 AM
I am trying to perform filtering not only on the columns that are visible, but also on the columns that may not be shown in the column list. Has anyone attempted doing that?

Thanks

ambience
28 Nov 2007, 9:56 AM
ambience, can you give some code to tell how can you do this
http://picasaweb.google.com/boyjunqiang/VFmYgC/photo#5137809191119357938
I try do this all day , :salmost give up :(

Ok, here is a Quick Stab at a conversion. I have not tested this and it most likely does not work as is (even if you had the missing proprietary parts). It's also not the most elegant code I've ever written and it depends on some tree search code both in JS and Java that I would have to check with the higher ups before I could share (doubtfull). Having said that, hopefully it should help point you in the right direction =)

TreeMenuItem.js


Ext.namespace('CP.menu');
CP.menu.TreeMenuItem = function(treeCls, treeOpts){
CP.menu.TreeMenuItem.superclass.constructor.call(this);
this.addEvents({select: true, search: true});

this.qTask = new Ext.util.DelayedTask(this.doQuery, this);
this.treeCls = treeCls;
this.treeOpts = treeOpts || {};
this.searchBox = new Ext.form.TextField();
};
Ext.extend(CP.menu.TreeMenuItem, Ext.menu.BaseItem, {
minHeight: 240,
minWidth: 200,
hideOnClick: false,
updateDelay: 500,
cls: 'tree-menu',
loadingText: 'Loading...',

onRender: function(container, position){
this.el = container;
this.searchBox.render(container.createChild({style: 'overflow: auto;'}));

this.treeDiv = container.createChild({cls: 'menu-tree', style: 'overflow: auto;'});
this.tree = this.buildTree(this.treeDiv);
this.tree.getSelectionModel().on('selectionchange', this.onSelect, this);

this.loading = this.treeDiv.createChild({cls: 'loading-indicator', html: this.loadingText, style: 'display: none;'});
this.tree.on('reloaded', function(){
this.loading.setDisplayed(false);
this.searchBox.el.dom.disabled = false;
if(this.loadedFn) this.loadedFn();
}, this);

this.searchBox.el.on('keyup', function(){this.qTask.delay(this.updateDelay);}, this);

var resizer = new Ext.Resizable(this.el, {
pinned:true, handles:'se'
});
resizer.on('resize', function(rsz, w, h){
this.resize(w, h);
this.parentMenu.autoWidth();
this.parentMenu.el.show();
}, this);

this.resize(this.minWidth, this.minHeight);

this.doQuery();
},

buildTree: function(el){
var tree = new this.treeCls(el, this.treeOpts);
tree.render();

return tree;
},

onSelect: function(model, node){
this.fireEvent('select', node.id, node.text);
},

doQuery: function(callback){
var value = this.searchBox.getValue();

this.loadedFn = callback;
this.loading.setDisplayed(true);
this.searchBox.el.dom.disabled = true;

this.tree.search(value.length > 0 ? value : null);

this.fireEvent('search', value);
},

setValue: function(id, search){
if(search)
this.searchBox.setValue(search);

this.fireEvent('select', id, search);
},

resize: function(w, h){
var search = this.searchBox.getEl();
var padding = this.el.getFrameWidth('tb');
search.setWidth(w - this.el.getFrameWidth('lr'));
this.treeDiv.setWidth(w);
this.treeDiv.setHeight(h - search.getHeight() - padding - 7);
}
});


PolicyControl.js


CP.grid.filters.PolicyControl = Ext.extend(Ext.ux.grid.filter.Filter, {
updateDelay: 500,

init: function(menu){
this.data = {};
this.updateTask = new Ext.util.DelayedTask(this.fireUpdate, this);

var items = this.items = [
new Ext.menu.CheckItem({text: 'ID', menu: this.buildIdMenu()}),
new Ext.menu.CheckItem({text: 'Category', menu: this.buildCategoryMenu()}),
new Ext.menu.CheckItem({text: 'Contains Text', menu: this.buildSearchMenu()}),
new Ext.menu.CheckItem({text: 'Child of ' + Naming.PolicyObject['short'], menu: this.buildPolicyMenu()})
];

for(var i=0; i<items.length; i++)
items[i].on('checkchange', function(i, item, checked){
this.fireUpdate();
if(checked) this.setChecked(i);
}.bind(this, i));

this.menu.add(items[0], '-', items[1], items[2], items[3]);
},

buildIdMenu: function(){
this.idMenu = new CP.menu.NumericMenu({updateDelay: this.updateDelay});
this.idMenu.on('update', function(){
this.setChecked(0);
this.fireUpdate();
}, this);

return this.idMenu;
},

buildSearchMenu: function(){
var menu = this.searchMenu = new Ext.menu.Menu();
var item = this.nameSearch = new EditableMenuItem("", {icon: '/img/small_icons/famfamfam/find.png'});
item.on('keyup', function(event){
this.setChecked(2);
if(event.getKey() == event.ENTER){
menu.hide(true);
return;
}

this.data.search = item.getValue();
this.updateTask.delay(this.updateDelay);
}.bind(this));
menu.add(item);

return menu;
},

buildPolicyMenu: function(){
var menu = this.policyObjectMenu = new Ext.menu.Menu();
var mi = this.pcMenuItem = new CP.menu.TreeMenuItem(ProgramTree, {
showControls: false,
editable: false
});
mi.on('select', function(id, name){
menu.hide(true);
this.setChecked(3);
this.fireUpdate();
this.data.parentId = id;
this.data.parentName = name;
}, this);
menu.add(mi);
return menu;
},

buildCategoryMenu: function(){
var menu = this.categoryMenu = new CP.menu.CategoryMenu();
menu.on('updated', function(){
this.setChecked(1);
this.fireUpdate();
}, this);

return menu;
},

getValue: function(){
if(this.items[0].checked){
var values = this.idMenu.getValues()
var args = [];
if(values.lt)
args = [{type: 'policyControl', mode: 'id', comparison: 'lt', value: values.lt}];
if(values.gt)
args.push({type: 'policyControl', mode: 'id', comparison: 'gt', value: values.gt});
if(values.eq)
args = {type: 'policyControl', mode: 'id', comparison: 'eq', value: values.eq};

return args;

} else {
var data = [];
if(this.items[1].checked){
var cd = this.categoryMenu.getValues();
data.push({
type: 'policyControl',
mode: 'category',
category: cd.parent,
subCategory: cd.child
});
}
if(this.items[2].checked){
data.push({
type: 'policyControl',
mode: 'search',
value: this.data.search
});
}
if(this.items[3].checked){
data.push({
type: 'policyControl',
mode: 'children',
value: this.data.parentId,
parentName: this.data.parentName
});
}

return data;
}
},

setValue: function(data){
data = typeof data.length != 'undefined' ? data : [data];
data.each(function(data){
if(data.mode == 'id'){
arg = {};
arg[data.comparison] = data.value;
this.idMenu.setValues(arg);
this.setChecked(0);
} else if(data.mode == 'category') {
this.categoryMenu.setValues({parent: data.category, child: data.subCategory});
this.setChecked(1);
} else if(data.mode == 'search') {
this.nameSearch.setValue(data.value);
this.setChecked(2);
} else if(data.mode == 'children') {
this.pcMenuItem.setValue(data.value, data.parentName);
this.setChecked(3);
}
}.bind(this));

this.fireEvent('update', this);
},

fireUpdate: function(){
if(this.enabled)
this.fireEvent('update', this);

this.setActive(true);
},

setChecked: function(index){
this.items[index].setChecked(true, true);

if(index > 0)
this.items[0].setChecked(false, true);
else
for(var i=1; i<4; i++)
this.items[i].setChecked(false, true);
}
});
CP.menu.CategoryMenu = function(){
CP.menu.CategoryMenu.superclass.constructor.call(this);
this.addEvents({updated: true});
this.data = {};
this.build();
};
Ext.extend(CP.menu.CategoryMenu, Ext.menu.Menu, {
build: function(){
var data = Ajax.JSONGetObject('.../getCategoryTree').getData();

for(var i=0; i<data.length; i++){
var subMenu = new Ext.menu.Menu();

var categoryItem = new Ext.menu.CheckItem({text: data[i].name, menu: subMenu, group: 'category', catId: data[i].id});
this.add(categoryItem);
categoryItem.on('checkchange', this.parentMenuChecked.bind(this, data[i].id));

data[i].children.each(function(child){
var item = new Ext.menu.CheckItem({text: child.name, group: 'subCategory', catId: child.id});
subMenu.add(item);
item.on('checkchange', this.subMenuChecked.bind(this, categoryItem));
}.bind(this));
}
},

parentMenuChecked: function(id){
if(this.lastActiveSubCat){
this.lastActiveSubCat.setChecked(false, true)
this.lastActiveSubCat = null;
delete this.data.subCategory;
}
this.data.category = id;
this.fireEvent('updated', this);
},

subMenuChecked: function(parentMenu, item, checked){
if(checked){
var pChecked = parentMenu.checked;
if(!pChecked)
parentMenu.setChecked(true);

this.lastActiveSubCat = item;
this.data.subCategory = item.catId;

if(pChecked)
this.fireEvent('updated', this);
}
},

getValues: function(){
return {parent: this.data.category, child: this.data.subCategory};
},

setValues: function(ids){
var parent = this.items.find(function(item){return ids.parent == item.catId});
if(parent){
parent.setChecked(true, true);

var child = parent.menu.items.find(function(item){return ids.child == item.catId});
if(child)
child.setChecked(true, true);

this.data.category = ids.parent;
this.data.subCategory = ids.child;
}
}
});

sjerry
28 Nov 2007, 10:09 AM
Great plugin, thanks

ambience
28 Nov 2007, 10:10 AM
I am trying to perform filtering not only on the columns that are visible, but also on the columns that may not be shown in the column list. Has anyone attempted doing that?

Thanks

Yes, I have implemented just such a scenario recently. What kind of problem are you running into?

chernomorez
28 Nov 2007, 10:43 AM
Ambience, thanks for a quick reply. First, would you mind pointing me to that implementation. The problem is that either the filters have to be outside of the menus, or there needs to be a column header for every filterable column. What I am trying to build though, is a way of filtering the records without displaying the column (or the column header).
Thanks again.


Yes, I have implemented just such a scenario recently. What kind of problem are you running into?

ambience
28 Nov 2007, 11:05 AM
I've created a quick variation on the demo here: http://ccinct.com/lab/filter-grid/hidden.html that demonstrates filtering by a field that is not part of the column listing.

chernomorez
28 Nov 2007, 3:14 PM
Thanks for the sample. I was actually trying to pull out all of the filters out of the menus onto a separate panel in tbar or bbar. Would you happen to have a sample for that also?


I've created a quick variation on the demo here: http://ccinct.com/lab/filter-grid/hidden.html that demonstrates filtering by a field that is not part of the column listing.

hendricd
28 Nov 2007, 3:16 PM
separate panel in tbar or bbar. Would you happen to have a sample for that also?


A couple of my previous posts on this thread discuss how the API can be used to do that.

boyjunqiang
28 Nov 2007, 5:27 PM
Ambience, thanks for a quick reply,the code are very usefull and I will try it :)

ambience
28 Nov 2007, 5:43 PM
I've added a "useMenu" config options to the filters that will prevent the menus from being shown if set to false. I am holding off on attaching the source until I can see if the Ext folks will change how state restoration happens slightly so that the plugin can piggyback the grid's state events.

elrems
29 Nov 2007, 1:27 AM
another live demo

http://soubeyrand.info/grid-filter (http://soubeyrand.info/ext-2.0/examples/grid-filter/index.html)

R

evilized
29 Nov 2007, 1:31 PM
is possible, can i use this estension with a autogrid component???

i've a lot of autogrid in my apps... but i need a filter for ... and this extension is like "all i need :)"

thx u for u work man.

hendricd
29 Nov 2007, 2:15 PM
It's right here in this thread (19 pages) somwhere..

Morris
30 Nov 2007, 3:33 AM
It works lovely with sample in this page.

Will you add support for visual feedback that a particular column has a filter supplied?

Here's some sample code to use it in Rails (not SQL injection safe btw, just the basic idea) :


MAPPING = {
'subject' => 'messages.subject',
'message_from' => 'concat(senders_messages.firstname, " ", senders_messages.lastname)',
'created_at' => 'created_at',
'read' => 'inboxes.is_read'
}

# Use same :conditions => conditions in query and count query
def conditions
cond = []
if params[:filter]
params[:filter].each_pair{|k, v|
# This is not SQL injection safe
cond << MAPPING[v['field']] + ' LIKE "%' + v['data']['value'] + '%"'
}
end
return cond.join ' AND ' if cond.size.nonzero?
nil
end

def includes
[:user, {:message => [:sender]}]
end

def inbox
messages = session[:user].message_inbox_items.find(:all,
:include => includes,
:limit => params[:limit] || nil,
:offset => params[:start] || nil,
:order => (MAPPING[params[:sort]] + ' ' + params[:dir]) || nil,
:conditions => conditions
)

headers['Content-Type'] ||= 'text/javascript'
render :text => inbox_items_to_json(messages)
end


I use MAPPING because you can't use dots in field names on the client side.

ambience
30 Nov 2007, 8:22 AM
I'm afraid I don't understand the request lol. It does support feed back by way of a custom class being applied to the header of any column with an active filter. It does not however, currently support styling the whole column as of yet, but Doug has provided a solution for that in a previous post.

mjlecomte
1 Dec 2007, 6:32 AM
Just curious if anyone is bothering to update the paging toolbar display (the text showing the total number displayed). By default the toolbar would indicate the total number of records displayed based on server side return. Once you filter it, you have an indication what the original count is, but not what the new (filtered) count is.
Besides the coding issue, I'm not sure what kind of display would be appropriate either. Even if I filter down to 30 of 100 original records, the user may want to see both in some format.

hendricd
1 Dec 2007, 6:53 AM
Just pass your GridFilter instance as a plugin for PagingToolbar and it will handle the record counts for you.

mjlecomte
2 Dec 2007, 8:14 AM
Just pass your GridFilter instance as a plugin for PagingToolbar and it will handle the record counts for you.

Will that work if you are filtering locally also? I have the plugin referenced into the paging toolbar, but right now I just have it working for local filtering.

The couple of examples I've seen posted for this plugin don't show the count.

hendricd
2 Dec 2007, 8:27 AM
I stand corrected.

After looking over the source, all that plugin reference does is reset the params.start to 0 for the eventual reload.

GridFilters doesn't update anything on PagingToolBar (local or remote). PageToolBar updates itself based on what's in the store, not "filtered of unfiltered".

ambience
3 Dec 2007, 9:42 AM
Correct me if I'm wrong, but this seems like a shortcoming in the paging toolbar. I am leveraging the filterBy function on the store in standard way.

hendricd
3 Dec 2007, 9:46 AM
@ambiance - yes no problem with GridFilter.


PageToolBar updates itself based on what's in the store, not "filtered of unfiltered". means just that. PagingToolBar reflects the store's current record count, nothing more. ;)

ambience
3 Dec 2007, 9:54 AM
Right I guess I should have quoted or "@mjlecomte", I understood your response =) My bad.

cbandes
3 Dec 2007, 12:54 PM
Hi - I am a total newb, please forgive me intrusion.

Where would be the best place to start? I want to build a filterable grid that will display data taken from SQL queries. Right now I'm just executing queries with php and dumping them into a table. I would like to have a lot more functionality, like that demonstrated here, but I don't even know where to begin looking. Could someone please point me in the right direction?

Thank you!

-Charley

hendricd
3 Dec 2007, 1:00 PM
Step 1: Spend a lot of time in /examples/grid (in your Ext distribution) first. Get a basic example running first, then again with your SQL backend, getting your SQL queries returning something the grid can render properly, only then.... [Post to the 2.0 Help forum if you get stuck]

Step 2: Roll in the GridFilter on top of it. [Post here for issues doing this]

Read those DOCS! Look at as much source code as you can !

oldroy
7 Dec 2007, 9:12 AM
Just noticed this and will tinker with it today. It's a thing of beauty - kind of like the "holy grail" of grouped, filtered grids. Thank you for letting others use it.

gameshints
7 Dec 2007, 12:08 PM
Stupid question, probably, but how exactly does this work?

I have a grid that displays information from an XML file. I easily got your plugin to install (I see the extra item in the column menus) ... but it doesn't filter.

Doesn't it just affect my "GroupingStore" object? or does it send information to the server, and I have to return different information in my XML file?

Thanks,

hendricd
7 Dec 2007, 12:19 PM
Active filter conditions are packaged up as params for submission during your store.load.

You server side query should evaluate them and filter your SQL resultset accordingly.

Or set GridFilter.local = true and it's filtered by the store instead.

mjlecomte
8 Dec 2007, 10:09 AM
Hi - I am a total newb, please forgive me intrusion.

Where would be the best place to start? I want to build a filterable grid that will display data taken from SQL queries. Right now I'm just executing queries with php and dumping them into a table. I would like to have a lot more functionality, like that demonstrated here, but I don't even know where to begin looking. Could someone please point me in the right direction?

Thank you!

-Charley


There's a working php example here (http://extjs.com/forum/showthread.php?t=18435&goto=newpost), however, the server side filtering is not included (at least not yet). If you use Firebug, you can check what is getting sent to the server side script to give you an idea of how to configure your sql queries. There was some sample php files somewhere in this thread that are in the zip file for the thread I'm mentioning, but they're not integrated into the example yet.

mjlecomte
8 Dec 2007, 10:16 AM
I noticed a performance hit in my example here (http://extjs.com/forum/showthread.php?t=18435&goto=newpost) after getting the filter up an running. I'm not saying the load time is solely attributable to the grid filter plugin, but I think it contributes to some of the increase (if nothing else because of the extra files that need to get loaded).

I also noticed that the cell renderers get looped through twice. I perceived that the cells get rendered once when the "original" store gets loaded and then again, when the data store gets filtered. Just curious if I'm seeing this correctly, I wasn't sure if I was setting something up wrong (where the cell rendering would only be done once). If it matters the above behavior was noticed with only local filtering, I haven't got server side filtering working yet.

hendricd
8 Dec 2007, 12:39 PM
I noticed a performance hit in my.., not saying the load time is solely attributable..I've found merging the Filter source 'packages' into a single JS file helped with that - a bit.

adinata
9 Dec 2007, 11:13 PM
I am having some problems using this plugin. I tried to add filters to the Grouping example. Here is my code. The html file


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Grid3 Grouping Example</title>

<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> </script><script type="text/javascript">_uacct = "UA-1396058-1";urchinTracker();</script>
<link rel="stylesheet" type="text/css" href="../../resources/css/xtheme-default.css" /><!-- LIBS -->
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>

<!-- ENDLIBS -->

<script type="text/javascript" src="../../ext-all.js"></script>


<script type="text/javascript" src="grouping.js"></script>
<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="grid-examples.css" />

<!-- Common Styles for the examples -->
<link rel="stylesheet" type="text/css" href="../examples.css" />

<style type="text/css">
body .x-panel {
margin-bottom:20px;
}
.icon-grid {
background-image:url(../shared/icons/fam/grid.png) !important;
}
#button-grid .x-panel-body {
border:1px solid #99bbe8;
border-top:0 none;
}
.add {
background-image:url(../shared/icons/fam/add.gif) !important;
}
.option {
background-image:url(../shared/icons/fam/plugin.gif) !important;
}
.remove {
background-image:url(../shared/icons/fam/delete.gif) !important;
}
.save {
background-image:url(../shared/icons/save.gif) !important;
}
</style>
</head>
<body>
<script type="text/javascript" src="../examples.js"></script><link rel="stylesheet" type="text/css" href="../lib.css" /><div id="lib-bar" class="x-toolbar" style="border-width:0 1px 1px"><div id="lib-bar-inner"> <span>Theme:</span>&#160;&#160;<select id="exttheme"><option value="default">Ext Blue</option><option value="gray">Gray Theme</option></select></div></div>
<h1>GridView3 Grouping</h1>
<p>Note that the js is not minified so it is readable. See <a href="grouping.js">grouping.js</a>.</p>

</body>
</html>

and grouping.js file is


/*
* Ext JS Library 2.0
* Copyright(c) 2006-2007, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/

Ext.onReady(function(){

Ext.QuickTips.init();

var xg = Ext.grid;

// shared reader
var reader = new Ext.data.ArrayReader({}, [
{name: 'company'},
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'},
{name: 'industry'},
{name: 'desc'}
]);

var filters = new Ext.ux.grid.GridFilters({filters:[
{type: 'string', dataIndex: 'company'},
{type: 'string', dataIndex: 'industry'},
{type: 'date', dataIndex: 'lastChange'}
]});

var grid = new xg.GridPanel({
store: new Ext.data.GroupingStore({
reader: reader,
data: xg.dummyData,
sortInfo:{field: 'company', direction: "ASC"},
groupField:'industry'
}),

columns: [
{id:'company',header: "Company", width: 20, sortable: true, dataIndex: 'company'},
{header: "Price", width: 20, sortable: true, renderer: Ext.util.Format.usMoney, dataIndex: 'price'},
{header: "Change", width: 20, sortable: true, dataIndex: 'change', renderer: Ext.util.Format.usMoney},
{header: "Industry", width: 20, sortable: true, dataIndex: 'industry'},
{header: "Last Updated", width: 20, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
],

view: new Ext.grid.GroupingView({
forceFit:true,
groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
}),

enableColLock: false,
loadMask: true,
plugins: filters,
frame:true,
width: 700,
height: 450,
collapsible: true,
animCollapse: false,
title: 'Grouping Example',
iconCls: 'icon-grid',
renderTo: document.body
});
});



// Array data for the grids
Ext.grid.dummyData = [
['3m Co',71.72,0.02,0.03,'4/2 12:00am', 'Manufacturing'],
['Alcoa Inc',29.01,0.42,1.47,'4/1 12:00am', 'Manufacturing'],
['Altria Group Inc',83.81,0.28,0.34,'4/3 12:00am', 'Manufacturing'],
['American Express Company',52.55,0.01,0.02,'4/8 12:00am', 'Finance'],
['American International Group, Inc.',64.13,0.31,0.49,'4/1 12:00am', 'Services'],
['AT&T Inc.',31.61,-0.48,-1.54,'4/8 12:00am', 'Services'],
['Boeing Co.',75.43,0.53,0.71,'4/8 12:00am', 'Manufacturing'],
['Caterpillar Inc.',67.27,0.92,1.39,'4/1 12:00am', 'Services'],
['Citigroup, Inc.',49.37,0.02,0.04,'4/4 12:00am', 'Finance'],
['E.I. du Pont de Nemours and Company',40.48,0.51,1.28,'4/1 12:00am', 'Manufacturing'],
['Exxon Mobil Corp',68.1,-0.43,-0.64,'4/3 12:00am', 'Manufacturing'],
['General Electric Company',34.14,-0.08,-0.23,'4/3 12:00am', 'Manufacturing'],
['General Motors Corporation',30.27,1.09,3.74,'4/3 12:00am', 'Automotive'],
['Hewlett-Packard Co.',36.53,-0.03,-0.08,'4/3 12:00am', 'Computer'],
['Honeywell Intl Inc',38.77,0.05,0.13,'4/3 12:00am', 'Manufacturing'],
['Intel Corporation',19.88,0.31,1.58,'4/2 12:00am', 'Computer'],
['International Business Machines',81.41,0.44,0.54,'4/1 12:00am', 'Computer'],
['Johnson & Johnson',64.72,0.06,0.09,'4/2 12:00am', 'Medical'],
['JP Morgan & Chase & Co',45.73,0.07,0.15,'4/2 12:00am', 'Finance'],
['McDonald\'s Corporation',36.76,0.86,2.40,'4/2 12:00am', 'Food'],
['Merck & Co., Inc.',40.96,0.41,1.01,'4/2 12:00am', 'Medical'],
['Microsoft Corporation',25.84,0.14,0.54,'4/2 12:00am', 'Computer'],
['Pfizer Inc',27.96,0.4,1.45,'4/8 12:00am', 'Services', 'Medical'],
['The Coca-Cola Company',45.07,0.26,0.58,'4/1 12:00am', 'Food'],
['The Home Depot, Inc.',34.64,0.35,1.02,'4/8 12:00am', 'Retail'],
['The Procter & Gamble Company',61.91,0.01,0.02,'4/1 12:00am', 'Manufacturing'],
['United Technologies Corporation',63.26,0.55,0.88,'4/1 12:00am', 'Computer'],
['Verizon Communications',35.57,0.39,1.11,'4/3 12:00am', 'Services'],
['Wal-Mart Stores, Inc.',45.45,0.73,1.63,'4/3 12:00am', 'Retail'],
['Walt Disney Company (The) (Holding Company)',29.89,0.24,0.81,'4/1 12:00am', 'Services']
];

// add in some dummy descriptions
for(var i = 0; i < Ext.grid.dummyData.length; i++){
Ext.grid.dummyData[i].push('Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed metus nibh, sodales a, porta at, vulputate eget, dui. Pellentesque ut nisl. Maecenas tortor turpis, interdum non, sodales non, iaculis ac, lacus. Vestibulum auctor, tortor quis iaculis malesuada, libero lectus bibendum purus, sit amet tincidunt quam turpis vel lacus. In pellentesque nisl non sem. Suspendisse nunc sem, pretium eget, cursus a, fringilla vel, urna.<br/><br/>Aliquam commodo ullamcorper erat. Nullam vel justo in neque porttitor laoreet. Aenean lacus dui, consequat eu, adipiscing eget, nonummy non, nisi. Morbi nunc est, dignissim non, ornare sed, luctus eu, massa. Vivamus eget quam. Vivamus tincidunt diam nec urna. Curabitur velit.');
}

The problem I get is that when I try to filter I get a permanent loading message. What am I doing wrong?

JeffHowden
10 Dec 2007, 3:51 AM
Have you verified that the server is getting a response it expects? Have you checked to see if maybe you're getting a response back from the server but it's malformed or something?

adinata
10 Dec 2007, 11:50 AM
Have you verified that the server is getting a response it expects? Have you checked to see if maybe you're getting a response back from the server but it's malformed or something?

All the data is stored in a local array and I would like to apply the filter on the local data. I was wondering if this had to do with the local: true config option. What is it's purpose and where should I set it?

adinata
10 Dec 2007, 4:07 PM
I played around with it a bit more and finally got it to work. I had to change data: xg.dummyData, to proxy: new Ext.data.MemoryProxy( xg.dummyData), and add filter.local = true

Can anyone tell me what proxy: new Ext.data.MemoryProxy( xg.dummyData), does in place of data: xg.dummyData

hendricd
10 Dec 2007, 4:15 PM
Ext.data.MemoryProxy provides the valuable event interactions with the store and its assigned Reader. Without it, simple arrays . ... well, would remain that way. ;)

mjlecomte
10 Dec 2007, 4:39 PM
I'm a little surprised you got it working when filters (columns specified in filters) do not match your column model (columns). In my attempts with this the filtering would not show up unless I specified a filter for every column in the column model.
Maybe I have other issues.:">

adinata
10 Dec 2007, 7:18 PM
I'm a little surprised you got it working when filters (columns specified in filters) do not match your column model (columns). In my attempts with this the filtering would not show up unless I specified a filter for every column in the column model.
Maybe I have other issues.:">

Oh sorry, I also changed the filter to match the columns.

ambience
11 Dec 2007, 9:54 AM
I'm a little surprised you got it working when filters (columns specified in filters) do not match your column model (columns). In my attempts with this the filtering would not show up unless I specified a filter for every column in the column model.
Maybe I have other issues.:">

That should not be the case, you should be able to include only the columns you want (and even some that are not in the gird).

mjlecomte
12 Dec 2007, 5:03 PM
That should not be the case, you should be able to include only the columns you want (and even some that are not in the gird).

I posted this problem in this thread before, I assume I'm doing something wrong. If I take a working grid with this plugin working filtering the grid, and then comment out one line of the "filters" var that specifies one of the column filters then the filter option no longer shows up for ANY column.
Any ideas what I'm doing wrong if this is not the expected behavior?

ambience
12 Dec 2007, 5:56 PM
I'll have to run some tests, but I am on vacation for 2 weeks. So it won't be till January sorry =(

eliasp
13 Dec 2007, 3:37 AM
Hi,

this plugin is exactly what I need for my current project - but: where's the source?
Is the one on the example page (http://ccinct.com/lab/filter-grid/) the most current?
Is there no central download page where I can always retrieve the latest release?

Regards, Elias P.

ambience
13 Dec 2007, 9:47 AM
Hi,

this plugin is exactly what I need for my current project - but: where's the source?
Is the one on the example page (http://ccinct.com/lab/filter-grid/) the most current?
Is there no central download page where I can always retrieve the latest release?

Regards, Elias P.

If you mean a wiki entry, no, not as of yet. The first post of this thread will always have the most current source attached.

ambience
13 Dec 2007, 9:51 AM
Hello there.

I've started this thread: http://extjs.com/forum/showthread.php?t=19010 and solved almost all my issues there.

But there is one last thing that is being hard to find out.

The grid is loading correctly and stuff, but the problem is that the search is still not working well..

Link:
http://www.ufu.br/ramais/


Code:


<?php

require_once 'db.inc.php';
$ramais = DB_DataObject::factory('ramal');

$start = $_GET['start'];
$limit = $_GET['limit'];
$sort = $_GET['sort'];
$dir = $_GET['dir'];
$filter = $_GET['filter'];

$where = "";

$strqry = " select
id_ramal,
ramal,
nome_ramal,
nome_campus
from
ramal, campus
where";

if(isset($filter))
{
$where = $where." nome_ramal";
$where = $where." like '%".$filter[0]['data']['value']."%'";
//$strqry = $strqry.$where." order by $sort $dir";
$strqry = $strqry.$where." limit $limit offset $start ";
}
else
{
$where = $where." campus.id_campus = ramal.id_campus";
$strqry = $strqry.$where." order by $sort $dir";
$strqry = $strqry." limit $limit offset $start ";
}

$resultado['total'] = $ramais->query($strqry);

$count = 0;
while ($ramais->fetch()) {

$resultado['ramais'][] = array(
'id_ramal' => $ramais->id_ramal,
'ramal' => $ramais->ramal,
'nome_ramal' => $ramais->nome_ramal,
'nome_campus' => $ramais->nome_campus
);
}

echo json_encode($resultado);
?>


Can you guys help me here?
The grid is not paging when search returns more than 50 results..

Thanks in advance.

Looking quickly at a return from your code, the value "total" in your json response is coming back as null. Pretty sure that will trip up the paging toolbar.

eliasp
14 Dec 2007, 12:16 AM
If you mean a wiki entry, no, not as of yet. The first post of this thread will always have the most current source attached.

Is this attachment only visible for 'Premium Members'? The only attached source I could find in this thread is the one at post#70988 (http://extjs.com/forum/showthread.php?p=70988#post70988) which is now more than 2 months old.

Your first post in this thread doesn't have any attachment.

Thank you & Regards, Elias P.

ambience
15 Dec 2007, 4:13 PM
Is this attachment only visible for 'Premium Members'? The only attached source I could find in this thread is the one at post#70988 (http://extjs.com/forum/showthread.php?p=70988#post70988) which is now more than 2 months old.

Your first post in this thread doesn't have any attachment.

Thank you & Regards, Elias P.

Oh! Sorry, I must have deleted it when I updated the example and forgotten to upload the newest code, thanks for catching that.

krdavis
17 Dec 2007, 8:28 AM
I see that one can download the PHP filter code, however, I read mention that this was ported from Java and the source was posted earlier. I can't find it anywhere, could someone be so kind as to point out if and where the Java filter code can be downloaded?

BTW, great plugin...

THX!

caturstudio
18 Dec 2007, 7:25 PM
Hi ambience,

Your filter works well,thanks for posting such a wonderful code
I m newbie and am learning through your code
so can i get a PHP file(ie action.php)so that i can try fetch from my database

Thanks in advance.:)

How, i can get the source code (action.php) ..?
where i can see it..

Thank's

RacingTomcat
19 Dec 2007, 7:08 AM
Adding the "local:true"-Option to the filter definition works well in IE for filtering a local data store.


var filters = new Ext.ux.grid.GridFilters({
local:true,
filters:[
{type: 'numeric', dataIndex: 'id'},
{type: 'string', dataIndex: 'name'},
{type: 'string', dataIndex: 'plz'},
{type: 'string', dataIndex: 'ort'},
{type: 'string', dataIndex: 'land'}
]});

But the Firefox seems to ignore this Option.
Can anyone say something about this?

jlagedo
19 Dec 2007, 7:28 AM
Well it's just me but there's no code atached again in the first post of this thread :)

froamer
19 Dec 2007, 11:15 PM
If anyone is looking to get the filter data sent to the server in JSON format, this will do it...

Ext.override( Ext.ux.grid.GridFilters , {
buildQuery : function(filters) {
return {filters: Ext.encode(filters)};
}
});
Simple for EXTperts, but might be useful to others. I hope it helps.

Troy Wolf
20 Dec 2007, 6:57 AM
I just finished my grid with all the search options and stuff..
http://www.ufu.br/ramais/

Now i need to do the following:

I need to change the color of some particular rows (because they will have some sub-information on it)..
Also, when i double click this row, it will show this sub-information about that specific row..
Is there an example for that?

I'm trying to do something just like this:
http://www.sk-typo3.de/index.php?id=345

Double click on a row and you guys will see it "pops up a dialog with additional information".

Thanks in advance.
Uh....then USE the example at the link you provided as your learning resource. What more do you want? Download his javascript and see how he does it. Ultimately that's what you want, right? A working code example to do exactly what you want. :)

mjlecomte
21 Dec 2007, 5:37 AM
Yeah, but thats typo3 and extjs1.0...
I'm trying to use that as an example, but i'm not having any kind of success..
An extjs2.0 example would probably solv my problem.. :)

This is an editor grid example (http://extjs.com/forum/showthread.php?t=18435) (ext 2.0, filters, instead of double click it uses right click for options, and "properties" option of right click does similar to show other info of record). Oh, and the cell/row renderers to highlight rows are also in it.

Troy Wolf
21 Dec 2007, 6:03 AM
Jack, maybe this will help. It is some of my Ext2.0 code where I have a grid and the users can double-click a row to pop a detail window. I think this is exactly what you want.

The code below does not include how to build your store, reader, or grid. It shows you how once you have those things, you can add a detail window that pops up on row selection. ~o)

NOTE: This is actually javascript, but the PHP code tool gives nice syntax highlighting.


// I am using a read-only form to display the row's details.
myGrid.detailForm = new Ext.form.FormPanel({
bodyStyle:'padding:5px',
defaultType:'textfield',
defaults:{readOnly:true, width:360, selectOnFocus:true},
items: [
{fieldLabel:'Log Level', name:'log_level'},
{fieldLabel:'Sequence #', name:'sequence_nbr'},
{fieldLabel:'Timestamp', name:'ts'},
{fieldLabel:'Process Name', name:'process_name'},
{fieldLabel:'Script Name', name:'script_name'},
{xtype:'textarea', fieldLabel:'Message', name:'message', hideLabel:true, height:140, width:465}
]
})

// This is my detail window that pops up.
// Notice the form above (detailForm) is an 'item' of this window.
// It includes buttons to select the previous and next row from the grid.
myGrid.detailWin = new Ext.Window({
title: "Log Event Detail",
plain:false,
layout:'fit',
width:494,
height:350,
closeAction:'hide',
items:[myGrid.detailForm],
buttons: [
{
id:'btn-myGrid-detail-previous',
text:"Previous",
handler: function(){ myGrid.getSelectionModel().selectPrevious(); }
},
{
id:'btn-myGrid-detail-next',
text:"Next",
handler: function(){ myGrid.getSelectionModel().selectNext(); }
},
{text:"Close", handler: function(){myGrid.detailWin.hide();} }
],
keys: [{
key: [Ext.EventObject.UP, Ext.EventObject.DOWN],
fn: function(){ myGrid.getView().focusEl.focus(); }
}]
});

// This is how I grab the data detail for the specific row the user has selected.
myGrid.getSelectionModel().on('rowselect', function( sm, rowIndex, r){
myGrid.detailForm.data = r.data;
myGrid.detailForm.getForm().setValues(r.data);
});

// This is how I pop the window on double-click.
myGrid.on("rowdblclick", function(myGrid, rowIndex, e) {
myGrid.detailWin.show(myGrid.getActionEl());
myGridDetailButtonState();
});

ambience
22 Dec 2007, 1:46 PM
I am not sure why my attachment keeps getting deleted from the first post. Any one have any ideas? Regardless, the source will always be available through the example site.

sanjshah
22 Dec 2007, 5:37 PM
ambience,

thanks for a great plugin, would it possible to get a asp (MS Access) example to retrieve and send data back to a database?

Regards,

Sanj

cocorossello
22 Dec 2007, 5:43 PM
Hi,

I have implemented another kind filters in my application.

It's not actually a plugin, i make filters especially for each grid (see image).

Im building the filters appending divs in the top toolbar and then render a textfield (or combobox or whatever). So its a really big problem, becouse i have to disable resizing columns and code reuse is limited.

Now i need to pack a filtering grid becouse ill have a lot of filtering grids in my application. So i guess the best solution is to put the filters in the columnmodel (maybe in a second header...).

Anyone has an idea?

I post 2 screenshots from my custom filtering grids. I can just post some columns becouse the other ones have private data ;)

Hope we can pack in a class this kind of filtering grids!!

JorisA
22 Dec 2007, 7:04 PM
Hm I like your idea cocorossello.
I think its important to always show the current filters, but I like the possibility to set multiple filters as well (like in between to dates). Maybe we indead should add a second header row with filter values.

By the way, how do you set initial filter values. (especially for the date filter)

cocorossello
23 Dec 2007, 4:28 AM
Hm I like your idea cocorossello.
I think its important to always show the current filters, but I like the possibility to set multiple filters as well (like in between to dates). Maybe we indead should add a second header row with filter values.

By the way, how do you set initial filter values. (especially for the date filter)


Well, you can't do "greater or less than" filters with my idea, its more limited but more user friendly. I actually put that kind of filters in the bottom toolbar (i have very few of those).

Filters are just regular ext fields, to create a filter you have to pass a field config like this one:


{
xtype:'combo'
store: new Ext.data.SimpleStore({
fields: ['id', 'nombre'],
data : [....]
}),
displayField:'nombre',
valueField:'id',
editable: false,
mode: 'local',
typeAhead: false,
triggerAction:'all',
forceSelection:true,
editable:false,
name: 'comienzaPor',
allowBlank:false
}



Right now im trying to add a second top toolbar to the grid to render those filters. I'll also need to catch column move or resize events (and hide) to sincronize filters width and position with the columns.

JorisA
23 Dec 2007, 6:46 AM
Have a look at the Tasks example. It handles a additional header with collumn width sync.

cocorossello
23 Dec 2007, 1:30 PM
Thx!!

Tasks example was what i needed. Let me fix 1 or 2 resize-layout bugs and ill post the extension

sethladd
24 Dec 2007, 11:31 AM
Hello,

I've applied this Filter plugin to my Grid, and I'm able to filter my columns. Great work and thanks for sharing this great plugin.

I do have a small issue, though, and I'm hoping someone can lend a hand. In my paging toolbar, NaN is displayed for the current page. Note that the correct number of total items is displayed. It says: "Page NaN of 2253" for instance. I have attached a screen shot illustrating this.

This behavior appears once I add the plugin to the Grid. Adding the plugin to the Paging Toolbar does not fix this. Removing the plugin from the Grid returns the Paging display to normal (that is, before the plugin, paging displayed the correct numbers).

Any idea why I see NaN? I've included my Ext JS code in the hopes that someone can help.

Thanks very much!



Ext.onReady(function() {

Ext.ux.menu.RangeMenu.prototype.icons = {
gt: '/images/ux/greater_then.png',
lt: '/images/ux/less_then.png',
eq: '/images/ux/equals.png'
};
Ext.ux.grid.filter.StringFilter.prototype.icon = '/images/ux/find.png';

var filters = new Ext.ux.grid.GridFilters({filters:[
{type: 'string', dataIndex: 'uic'},
{type: 'string', dataIndex: 'short_name'},
{type: 'string', dataIndex: 'long_name'},
{
type: 'list',
dataIndex: 'service',
options: ['Air Force', 'Army', 'Marine Corps', 'Navy'],
phpMode: true
},
]});

var proxy = new Ext.data.HttpProxy({
url: '<%= formatted_directory_units_path(:format => :json) %>',
method: 'GET'
});

var store = new Ext.data.Store({
remoteSort: true,
sortInfo: {field: 'uic', direction: 'ASC'},
proxy: proxy,
reader: new Ext.data.JsonReader({
fields: ['uic','short_name','long_name','service'],
totalProperty: 'results',
root: 'units'
})
});

var pagingBar = new Ext.PagingToolbar({
pageSize: 50,
store: store,
displayInfo: true,
displayMsg: 'Displaying units {0} - {1} of {2}',
emptyMsg: "No units to display",
plugins: filters
});

var grid = new Ext.grid.GridPanel({
store: store,
columns: [
{header: 'UIC', sortable: true, dataIndex: 'uic',
renderer: function(value, cell_metadata, record, row, col, store) {
return '<a href="/units/'+value+'">'+value+'</a>';
}
},
{header: 'Short Name', sortable: true, dataIndex: 'short_name'},
{header: 'Long Name', sortable: true, dataIndex: 'long_name'},
{header: 'Service', sortable: true, dataIndex: 'service'}
],
viewConfig: {
forceFit: true
},
renderTo: 'units-table',
title: 'Units',
frame: true,
width: 900,
autoHeight: true,
autoScroll: true,
tbar: pagingBar,
plugins: filters
});

grid.render();

store.load();

});

hendricd
24 Dec 2007, 11:53 AM
You need to set some limits with your load request: ;)


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

Without that (and a script serverside that acks the limit) you'll get 116k+

sethladd
24 Dec 2007, 12:10 PM
Thanks for the clarification! Somewhere in my hacking around, I switched from autoLoad to the load call at the end. Adding those params worked great!

froamer
28 Dec 2007, 2:40 AM
Hi, great plugin!

I have filtering working with a grouping and paging grid and it works great apart from one small glitch...

If you are on a page number other than one, then apply a filter that reduces the hits, you can end up with a blank page and have to manually return to page 1 to see the filtered rows.

It would be much better to set the page number to 1 after a filter is applied. I can see there is a filterupdate event I could hook into, but after lots of forum searching I can't find a way to set the page number back to 1 in the PagingToolbar.

Any ideas?

JorisA
28 Dec 2007, 6:06 AM
To go back to page one, do store.load({params:{start:0,limit:pagingBar.pageSize} });

ambience
29 Dec 2007, 8:24 PM
You should also be able to pass the filters as a plugin to your paging tool bar (as in the example) and it will automatically set the page to 1 when there is a change to the filter configuration.

mariposil
31 Dec 2007, 9:02 AM
Hi to all and happy new year.

What about reconfigure in filter grid?

When i apply reconfigure to a filter grid with a new store and a new columnmodel all works fine except for the filters, they disappear from the columns menu...

Someone knows if is it possible to change the filter definition to a reconfigured grid?

Thanks.

hendricd
31 Dec 2007, 10:50 AM
Should be able to try:



grid.reconfigure(....);
grid.filters.init(grid);


But, the stores' beforeload event handler may fire twice if you're not changing the store in the reconfigure.

mariposil
1 Jan 2008, 3:21 AM
Thanks a lot for your answer.
It doesn't work for me... I'm a newbie with ext and I'm trying to learn. I decided to post this problem because i don't find clues in samples or ext docs and i spend 5 hours trying to solve it...
Now i'm doing this:


grid.reconfigure(mynewds, mynewcm);
grid.filters = mynewfilter;
grid.filters.init(grid);
mynewds.load({params:{start: 0, limit: 15}});

and the grid accepts the new datastore and columnmodel but the filter menu doesn't appear.

Thanks again for your help.

Have a nice day.

mariposil
1 Jan 2008, 6:51 AM
After more playing i discovered some issues:
grid.filters.init(grid); don't do the trick because don't create the new filter menu when the grid is reconfigured.
The filter menu is added in onRender event.

franck34
2 Jan 2008, 8:47 PM
Thanks to share this great plugin.

Is it normal that when i have
{"response":{"value":{"total_count":"0","version":1}}}
in my json response, the grid don't refresh ? (previous grid result are staying)

Franck

nedkopenev
3 Jan 2008, 7:21 AM
Hi everybody,
how do you pass from the server an array of list options for the filter. I put my list options in the json where my table data is but I don't know how to read it.

froamer
3 Jan 2008, 9:53 AM
You should also be able to pass the filters as a plugin to your paging tool bar (as in the example) and it will automatically set the page to 1 when there is a change to the filter configuration.

Thanks ambience, works great. FYI it also works alongside the Ext.ux.Andrie.pPageSize plug-in.

hendricd
3 Jan 2008, 9:58 AM
:-? Still scratchin my head over the 'grid-filters-reconfigure' dream [ nightmare ] .

mariposil
3 Jan 2008, 4:10 PM
Hi hendricd.
I lost 8 hours with this. This part of code does not return a valid value after reconfigure:

getMenuFilter: function(){

var view = this.grid.getView();
if(!view || view.hdCtxIndex === undefined)
return null;

return this.filters.get(

view.cm.config[view.hdCtxIndex].dataIndex);
}

view.cm.config[view.hdCtxIndex].dataIndex don't work as expected after reconfigure the grid. I don't know why.
Please send a clue if you win.:-/

hendricd
3 Jan 2008, 10:26 PM
pfffftt. 8 Hours, thats'a nothingg !

Yes, much of the filters functionality depends on the grid views' initial rendering, it would seem. One might need only simulate that effect some how in the reconfig. :-?

robasi
4 Jan 2008, 12:05 PM
Can you post an exmaple of how to use a list type with a datastore for options? Are there plans to have a filter using a combobox?

JorisA
7 Jan 2008, 4:15 PM
robasi: Have a look of listfilter.js. I guess it shouldn't be that hard to create a new filter that uses a combo.

And is there any chance to configure the icon locations in css rather then in javascript? In my opinion it would be best to use iconCls.

cocorossello
8 Jan 2008, 1:06 AM
Hi,

I have another kind of filters, if anyone is interested. At the moment, they only work for 'remote' grids, and the idea is more limited as you can't do all kinds of filters, but you can do text searches or combos or date (whatever kind of ext field).

The idea is that the filter is always visible and is in the column model. So you define columns like:



columns:[
{header:'Name',width:100,id:'name',dataIndex:'name',sortable:true,filter:{xtype:'textfield',name:'name'}},
{id:'id',dataIndex:'id',hidden:true}
]


You have to get the filters before reloading the store. Just like:


store.on('beforeload', function(){
var sf=grid.searchFields;
for(var i=0;i<sf.length;i++){
if(sf[i])
store.baseParams[sf[i].getName()]=sf[i].getValue();
}


I havent done the integration with these filters (that would be great, though i havent enough time right now). If people is interested, we can take a look.

JorisA
8 Jan 2008, 5:23 AM
cocorossello awesome :)
I think this makes it much better to understand for the user. For me the ultimate grid filter would be a combination between this layout, and the filter menu:

For strings and stuff regular fields like this, and for dates or lists a readonly field, with a menu that will update the value (for example 'between may 5 and aug 5', or 'after may 6')