Posted in ColdFusion | Posted on 06-01-2007 | 4,728 views
One of the cool new UI elements we have in ColdFusion 8 is the AJAX based grid. It can be bound to external data and allows for sorting and paging. This is pretty cool and all - and I'll blog more about it later, but I wanted to talk about a small little function that is used to help drive the grid - queryConvertForGrid.
Before you can hook up a cfgrid to the result of a CFC, you have to format the data in a special way. Instead of just returning a query, you must return a structure with two keys: query and totalrowcount.
The query is not your complete recordset. Instead, it is the current "page" of data. All cfgrid AJAX requests will pass to your CFC the current page. So you might think that you need to do a bit of math to figure out the current "slice" of data to return. You certainly could too - but this is where queryConvertForGrid comes into play.
So lets take a concrete example. You may remember my Traffic demo from yesterday. This demo used a grid that spoke to a CFC that in turn spoke to my Yahoo engine (which in turn spoke to Yahoo's services). The grid "spoke" to my CFC and passed along:
- The page to fetch
- The size of my pages
- SortCol and SortDir (not discussed today)
- And the Zip Code
My CFC then handled getting the data (and potentially sorting). But to return the proper data, I simply used queryConvertForGrid. This function takes three arguments: A query, a page number, and the page size. Here is a simple example using a pre-built query:
2
3<cfscript>
4for(i=1; i <= 200; i++) {
5 queryAddRow(foo);
6 querySetCell(foo, "id", i, i);
7 querySetCell(foo, "name", "Name #i#", i);
8 querySetCell(foo, "age", randRange(18,65), i);
9 querySetCell(foo, "gender", listGetAt("male,female", randRange(1,2)), i);
10}
11</cfscript>
12
13<cfset slice1 = queryConvertForGrid(foo, 1, 20)>
14<cfset slice2 = queryConvertForGrid(foo, 2, 20)>
15<cfset slicex = queryConvertForGrid(foo, 99, 20)>
16
17<cfdump var="#slice1#" label="First Page">
18<cfdump var="#slice2#" label="Second Page">
19<cfdump var="#slicex#" label="Page 99">
I have three calls to the queryConvertForGrid function. Each one passes in my query. The first call gets page 1. The second gets page 2. The last gets page 99. If you run this, you will see that each dump returns a slice of the initial 200 row query. You will also notice that it fails silently on page 99. (Is that good? Bad? I'm not sure.)
So as you can see, this function takes out some of the grunt work we have to do in order to hook up our CFCs to the new AJAX goodness on the front end.
Now I do have one point I'd like folks to consider. This function makes it super easy to get the page. But I'm still getting all 200 rows up front. You may want to consider doing your paging in SQL, especially MySQL since it makes it so easy. In fact, you can even write a query in MySQL that will get both a "page" and the total row count. (I discussed this here.) So if you can easily do the paging yourself, it may make sense to do so and improve the performance of your application.
In my next entry I'll give a nice complete demo of cfgrid and a bound CFC. And lastly - I have to admit that the cfscript block above just makes me plain giddy. (Yes, I'm a Scorpio Geek.)


Why can't you just pass in a query to cfgrid (seems like that would be easier and more consistent with the rest of the language)?
Glad to hear it! So why does paging require the extra structure?
<cfset myCFC = application.serviceFactory.getBean("ArticleGateway")>
I can do this: <cfset newsList = myCFC.getNewsForGrid(1,20)>
But I can't do this:
<cfgrid name="news"
format="html"
pagesize="10"
striperows="yes" bind="cfc:myCFC.getNewsForGrid({cfgridpage},
{cfgridpagesize},
{cfgridsortcolumn},
{cfgridsortdirection})"
selectmode="column"
appendKey="true">
Is it just not possible to get the CFC thru ColdSpring/Model-Glue and use the grid in this way?
index.cfm?event=getcrapforgrid&etcetc
<!--
1: HIDE ERROR CODE FROM USER
0: SHOW ERROR CODE FROM USER
1 = ON ; 0=OFF
-->
I have used <cfsetting showdebugoutput="no"> also. In comparing the response of both the servers (using Firebug), I suspect the problem lies with the _cf_rc value which is 0, while in the working version the value is 1. Is this the problem, If so, what is this variable and how do I control it? Any help will be greatly appreaciated.
Thanks!
As for the text you shared, that is not from CF, it is from something else in your code. I'd do a multi-file search for it.
I tested by inserting some HTML comments in the CFC just before the json output and the comments did not cause a problem. It is a problem only if it is in the appplication.cfm. I wonder why.
Thanks,
-Xavier
I simply point my Ajax to an event, like json.getFoo. The event does what it needs to do to get data, and then the view outputs the JSON.
I've even taken this a step further where I can broadcast "toJSON" in an event. I pass the name of the view State key to use, and then the generic toJSON event will get the value, convert to JSON, and use one generic view to output it.
[Add Comment] [Subscribe to Comments]