Filtering a CFGrid
Aug 12
So you want to filter a CFGrid huh? ColdFusion makes this easy!
First you need a CFC method that will return the query used to populate the grid. This method should take the cfgrid parameters and the value you want to filter on.
data.cfc:
2<cffunction name="getdata" access="remote" output="false"
3returntype="Any">
4<cfargument name="page"
5required="false" default="1" type="Numeric" />
6<cfargument name="pagesize" required="false" default="10" type="Numeric"
7/>
8<cfargument name="sortcolumn" required="false"
9default="" type="string" />
10<cfargument name="sortdir"
11required="false" default="ASC" type="string" />
12<cfargument name="filter" required="false" default="" type="String"
13/>>
14<cfset q =
15queryNew('id,name','integer,varchar') />
16<cfset queryaddrow(q,1) />
17<cfset querysetcell(q,'id',1)
18/>
19<cfset querysetcell(q,'name','sean') />
20<cfset queryaddrow(q,1) />
21<cfset
22querysetcell(q,'id',2) />
23<cfset
24querysetcell(q,'name','phillip') />
25<cfset queryaddrow(q,1) />
26<cfset querysetcell(q,'id',3)
27/>
28<cfset querysetcell(q,'name','steve') />
29<cfquery name="q" dbtype="query">
30select * from q
31<cfif
32len(trim(arguments.filter))>
33where name like <cfqueryparam cfsqltype="cf_sql_varchar"
34value="%#arguments.filter#%" />
35</cfif>
36<cfif
37len(trim(arguments.sortcolumn)) or len(trim(arguments.sortdir))>
38order by #arguments.sortcolumn# #arguments.sortdir#
39</cfif>
40</cfquery>
41<cfreturn
42queryConvertForGrid(q,arguments.page,arguments.pageSize) />
43</cffunction>
44</cfcomponent>
You can see here that I am just hard coding the query in, you would replace this with your cfquery call to your database or a call to your service layer, etc. Once you have your query results, you want to use the queryConvertForGrid method to format the result to a value that CFGrid can work with.
You then need a cfgrid! The trick here is how to get the grid to refresh as the user types a value in the filter box. ColdFusion Ajax UI tools have bind expressions that let us bind one control to another, and to react to events.
index.cfm:
2<p><label for="filter"><cfinput type="text" name="filter"
3id="filter" /></p>
4<cfgrid format="html"
5bind="cfc:data.getData({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},{filter@keyup})"
6name="grd" bindonload="true">
7<cfgridcolumn name="id" />
8<cfgridcolumn name="name" />
9</cfgrid>
10</cfform>
You can see my bind expression in the cf grid. It will call the getData method of my data.cfc and pass in the value from the "filter" input box whenever the key is released. ColdFusion provides other events you can react to as well, check the docs for details.
So now if you run index.cfm you will see a simple form with a text input and a grid. the grid will load when the page is run (bindonload="true") and as you type in the text box, the results are filtered.
EDIT: removed the example link as I have moved this blog to Railo



![[RSS]](/blog/template/rss.png)
#1 by Phillip Senn on 8/12/09 - 12:57 PM
I've used your example
for
http://www.cfmzengarden.com/CFMZenGarden/051
#2 by Sean Coyne on 8/12/09 - 1:05 PM
#3 by Adam on 8/13/09 - 11:31 AM
hidden attribute like id, appear in the textbox once the name is clicked
on in the grid?
#4 by Sean Coyne on 8/13/09 - 11:45 AM
you would want that to change, but you can bind the values in the grid
to any other form fields. You can see an example here
http://nm1m.blogspot.com/2008/01/binding-to-html-c...
#5 by Adam on 8/13/09 - 12:25 PM
Sean -
Thanks for the response. Please allow me to clarify. I have
a form that includes a textbox called "clientID." ClientID
includes an onClick event that loads a cfwindow called
"userWin." UserWin loads a cfgrid populated with a list of
clients. Above the grid is a textbox called "filter" to
filter the clients.
Once the clients are filtered and the specific
client is found, I would like to click on the client and have the hidden
clientID attribute to populate the textbox "clientID" on the
parent page.
<cfinput name="clientID"
type="text"
maxlength="8"
onClick="ColdFusion.Window.show('userWin')"
bind="{clientLookup.client}"
tabindex="1"
value="#form.clientID#"/>
<cfwindow
name="userWin"
title="Client
Lookup"
initshow="false"
modal="true"
center="true"
height="330"
width="330">
<cfoutput>
<cfform name="tableform" >
<cfinput type="text" name="filter" >
<cfgrid format="html"
name="clientLookup"
pagesize="10"
selectmode="single"
autowidth="true"
bind="cfc:client.getClients({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},
{filter@keyup})">
<cfgridcolumn name="client"
display="No"/>
<cfgridcolumn
name="firstname" header="FIRST NAME">
<cfgridcolumn name="lastname" header="LAST
NAME">
<cfgridcolumn name="organization"
header="ORGANIZATION">
</cfgrid>
</cfform>
</cfoutput>
</cfwindow>
I thought the code would help my explanation
:-)
Thanks.
#6 by Sean Coyne on 8/13/09 - 12:33 PM
the clientid cfinput within a cfform.
try something like
this:
<cfform>
<cfinput name="clientID"
type="text"
maxlength="8"
onClick="ColdFusion.Window.show('userWin')"
bind="{clientLookup.id}"
tabindex="1"
/>
</cfform>
<cfwindow
name="userWin"
title="Client
Lookup"
initshow="false"
modal="true"
center="true"
height="330"
width="330">
<cfoutput>
<cfform name="tableform" >
<cfinput type="text" name="filter" >
<cfgrid
format="html"
name="clientLookup"
pagesize="10"
selectmode="single"
autowidth="true"
bind="cfc:data.getdata({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},
{filter@keyup})">
<cfgridcolumn
name="id" />
<cfgridcolumn name="name"
>
</cfgrid>
</cfform>
</cfoutput>
</cfwindow>
#7 by Phillip Senn on 8/13/09 - 2:58 PM
while reading your blog, it disappears
after about a minute.
#8 by Sean Coyne on 8/13/09 - 3:02 PM
I turned them off.
#9 by Lonnie Broadnax on 5/22/10 - 7:27 PM
I've followed this blog and have a question of my own. Instead of filtering a cfgrid contents on a cfinput entry, I need to filter on the ID value from another cfgrid; like a Master/Detail relationship. I've had partial success using the following within the second cfgrid's definition:
<cfgrid name="Grid2"
width="450"
align="left"
format="html"
pagesize="10"
sort="true"
bind="cfc:myCFC.getDetailData({cfgridpage},
{cfgridpagesize},
{cfgridsortcolumn},
{cfgridsortdirection},
{Grid1.DetailID})"
It works fine for the first item in my Grid1 because the ID matches data from the cfc function populating Grid2. But when I move off of the matching Grid1 record and select a row without a matching ID value, Grid2 remains populated with the previous data and does not refresh.
Can you offer any insight in successfully filtering one cdgrid's data from another cfgrid?
Thanks in advance!
#10 by Sean Coyne on 5/22/10 - 7:38 PM
#11 by Marc on 6/8/10 - 6:48 AM
I just find this thread about CFgrid filtering. We are working on CF9.
I copy/paste the code, i haven't make any change. An error occurs when i launch the page : Error invoking CFC /DBUNIK/data.cfc : Error Executing Database Query
#12 by Sean Coyne on 6/8/10 - 10:41 AM
#13 by Jose Galdamez on 7/26/12 - 11:31 AM
http://www.raymondcamden.com/index.cfm/2010/4/29/C...
Then I saw your comment in that post and that led me here.
With these instructions I was able to get filtering working just fine. The part I was missing was the binding {filter@keyup}. With that in place all I had to do was tweak the business logic on the server side. I did run into hurdles while tweaking since I was trying to do it through ORM and my objects were layered. I hae to say debugging is where you really learn the nuts and bolts.
My only quibble with this style of filter is that there's a slight jitter as the grid updates. If my users complain I may just revert to something like jQuery Data Tables.
#14 by Sean Coyne on 7/26/12 - 2:08 PM
#15 by eugenekml on 10/30/12 - 4:18 AM
#16 by Sean Coyne on 10/30/12 - 10:07 AM