For adminstrative applications, most of my readers know I'm a huge proponent of the Ext JS library. But for front-end, consumer facing sites, I'm often pushed to use JQuery. JQuery is very light weight, and wonderful for DOM manipulation, but it isn't a component library. When you want widgets for advanced data display, you have to use something like JQueryUI. Unfortunately, JQueryUI doesn't yet have a grid component (though they are working on it). So when I recently needed a dynamic, paging data grid, I started looking for something that used server-side data requests and could be skinned using the ThemeRoller. That's when I came upon the DataTables plugin.
It took me some time to figure out the works of how the plugin makes server-side requests. What I found was that, by default the plugin passes an extreme amount of data on a request, and not typically in a format very conducive for our needs. I also had to find a way to pass the method name and data returnFormat needed. That's when I discovered that I could override it's default request. Once I figured that out, I wrote a method to parse the data to create a request object more conducive to a ColdFusion Component request. It passes the following arguments along in a request:
- iDisplayStart - The number of the first record in the requested set.
- iDisplayLength - The number of records to return in the requested set.
- sEcho - A DataTables request identifier, to be echoed back with the return.
- aoSort - If present, this will be a JSON string representation of sort columns and orders. It's an array of objects:
- colName - the column name
- sortDir - the sort direction (asc|desc)
After getting data to my CFC, I had to build my paging query. For my example here I wanted to use the MySQL database I use for my blog, so this was a learning experience for me. The biggest trick for me was getting the TotalCount of records, as this is extremely different from MS SQL, requiring two separate SQL statements for the query and the count. Since DataTables can also sort off of different columns, I needed a way to dynamically set the ORDER BY clause of the query. You can't bind parameters to the ORDER BY clause, but you want to protect your server from SQL injection attack, so you have to validate that part of the request (especially as it's an ajax request, which would be easier to manipulate). Pete Frietag came up with a little regex expression that could be used in this case.
We set up our component to return a structure in the following format:
- success - A boolean to denote success or failure of the request.
- message - Only returned if the request fails, a message to state why the failure occurred.
- totalCount - The total number of records available for the filters applied.
- result - The paging query.
The last piece of the puzzle was back on the client-side again, where the ColdFusion return had to be put back into a format that can be consumed by the DataTables plugin. This was actually very easy because of the way that ColdFusion returns query data.
Once I had these methods, I wanted to find out how to write a feature plugin for DataTables. One where I could identify additional config arguments in DataTables, and have it automatically work. I contacted Allan Jardine, who wrote DataTables (and has some great web dev tools on his site). He never wrote in that capability, saying that the method override was the only way to make this happen. What I did discover was that I could add options to the standard DataTables config. I created a new option for DataTables, oCFReaderDT, which takes an object of options. Only one argument is required, "method", to define the method to call in the CFC request. I also setup the processor to accept an option, "sForm", as a string selector of a form whose values you may need in the request (i.e.: 'form#myForm'). Then I wrote a custom function that encapsulated the previously written methods into one method, that could then be used as the value of the "fnServerData" option in the DataTables configuration object.
In the download link below is a zip file with all of the files for the example, which has been heavily commented so you know what's going on. Though written for ColdFusion 9, I have included both scripted and non-scripted CFC's. I hope you find this useful, and please leave any comments/questions/suggestions through the Comment Form or Contact links below.


#1 by Alan McCollough on 2/7/11 - 5:42 PM
#2 by Mike Henke on 2/7/11 - 9:29 PM
Or this CFWheels Datatables plugin https://github.com/mhenke/DataTablesForWheels
#3 by Steve 'Cutter' Blades on 2/9/11 - 6:05 PM
@Mike - I prefer to do the major munge processing (reformat of the incoming an outgoing) client side, taking the load off the server side. That way my CFC methods can focus on returning a simple struct, and I don't tie down the server with tasks I can distribute to the client. Stuff looks great though. (both of 'em)
#4 by Rachel Lehman on 3/11/11 - 3:56 PM
#5 by Steve 'Cutter' Blades on 3/12/11 - 9:20 AM
What? You and Adam don't have me permanently in your blog rolls? ;)
Yeah, it was an interesting exercise. Did you download the code and check out the custom reader?
I'm actually (right now) converting the grid I did at work from DataTables to jqGrid. I don't need the client side sorting (with paged data it makes more sense to hit the server), and their API and configuration options are more robust (not to mention you can actually trigger and listen for events).
Allen has done a great job with DataTables, and we've gone back and forth through the forums a few times and seems to be a super nice guy. I've offered to help make suggestions, and maybe contribute some code along the way, and he seemed real receptive. So, if/when I ever get some time....
Side Note: Tell Adam thanks for the intro with Ed. Great convo yesterday.
#6 by Madeleine McJones on 10/18/12 - 10:45 PM
#7 by Cutter on 11/3/12 - 11:14 AM
http://www.cutterscrossing.com/index.cfm/2007/4/29...
#8 by Joe Mali on 12/11/12 - 3:01 PM
Here is what the CFC is returning:
{"totalCount":98799,"result":{"COLUMNS":["LNAME"],"DATA":[["a"],["aab"],["Aaberg"],["Aaby"],["Aadland"],["Aagaard"],["Aakre"],["Aaland"],["Aalbers"],["Aalderink"],["Aalund"],["Aamodt"],["Aamot"],["Aanderud"],["Aanenson"]]},"sEcho":"1","success":true}
Thanks.
#9 by Cutter on 1/25/13 - 9:04 AM
I wrote this almost two years ago, and there have been many updates, both to DataTables and JQuery in general. I can't dig in right now, but please let us know if you make any changes we can share with others.
#10 by Edward Beckett on 4/2/13 - 3:10 AM
much appreciated chief ...