Posted in jQuery, ColdFusion | Posted on 03-17-2009 | 12,859 views
Earlier last week a reader (and forgive me, I wrote down your idea, not your name) asked for a simple demonstration of how to use jQuery to load in a ColdFusion query via Ajax. I whipped up a quick, and hopefully simple, set of demos to help show how easy this is.
First, please remember that there are many ways we can this. Just like ColdFusion provides many ways to skin the cat, so does jQuery. I'm going to demonstrate two main ways as I feel it really shows the two types of Ajax calls most folks will use.
In broad terms, most folks will use Ajax to either load rendered content or pure data. So let's say you want to show a list of people on a page. You want to load this via Ajax. You could have the server return the list, printed out with HTML, line breaks, etc. This is rather simple and is especially useful for times when your formatting needs are complex. It is a heck of a lot easier to format dates in ColdFusion then JavaScript. (Although I bet jQuery has a good date library!)
The alternative is to load pure data. This can be XML or JSON (typically JSON) which is then handled on the client. This requires more work, but typically results in less 'traffic' as you are only sending the data, not data plus formatting.
So which should you use? Whichever works best for you! (Yes, I know, a non-answer. Sorry.) Here are two demos of both in action.
2
3<head>
4<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
5<script>
6
7function loadQuery() {
8 $.get('data.cfm',{},function(data){
9 $("#content").html(data)
10 })
11 return false
12}
13
14$(document).ready(function() {
15 $("#loadLink").click(loadQuery)
16});
17
18</script>
19</head>
20
21<body>
22
23<p>
24 <a href="" id="loadLink">Load Query</a>
25</p>
26
27<div id="content">
28</div>
29
30</body>
31
32</html>
In my first example, I have a simple page that consists of one link and one empty div. Notice then loadQuery handles making the Ajax request and publishing it to the empty div. The ColdFusion file handles both creating the query and rendering it (although normally I'd get the query elsewhere, from a CFC for example):
2
3<cfset queryAddRow(q)>
4<cfset querySetCell(q, "person", "Scott Slone")>
5<cfset querySetCell(q, "coolness", "100")>
6
7<cfset queryAddRow(q)>
8<cfset querySetCell(q, "person", "Scott Stroz")>
9<cfset querySetCell(q, "coolness", randRange(1,100))>
10
11<cfset queryAddRow(q)>
12<cfset querySetCell(q, "person", "Raymond Camden")>
13<cfset querySetCell(q, "coolness", randRange(1,100))>
14
15<cfset queryAddRow(q)>
16<cfset querySetCell(q, "person", "Todd Sharp")>
17<cfset querySetCell(q, "coolness", randRange(1,100))>
18
19<cfset queryAddRow(q)>
20<cfset querySetCell(q, "person", "Scott Pinkston")>
21<cfset querySetCell(q, "coolness", randRange(1,100))>
22
23<h1>People</h1>
24
25<cfoutput query="q">
26<b>#person#</b> has a cool score of #coolness#.<br/>
27</cfoutput>
There isn't anything special about the query, except for a shout out to Scott Slone for feeding my Star Wars addiction via woot.com today!
You can see this in action here: http://www.coldfusionjedi.com/demos/jquerycfquery/test1.html.
Now let's look at the alternative. I'll start on the server side first. Here is data2.cfm. Same query, but now we serve it up as JSON and don't perform any formatting:
2... querySetCells cut from code to make it shorter ...
3
4<cfset data = serializeJSON(q)>
5<cfcontent type="application/json" reset="true"><cfoutput>#data#</cfoutput>
The front end now needs to get a bit more complex. I've only modified the loadQuery function so I'll just paste in that:
2 $.getJSON('data2.cfm',{},function(data){
3
4 //map columns to names
5 var columnMap = {}
6
7 for (var i = 0; i < data.COLUMNS.length; i++) {
8 columnMap[data.COLUMNS[i]] = i
9 }
10
11 //begin making my str
12 var str = '<h1>People</h1>'
13
14 for (var i = 0; i < data.DATA.length; i++) {
15 str += '<b>'+data.DATA[i][columnMap.PERSON]+'</b>'
16 str += ' has a cool score of '+data.DATA[i][columnMap.COOLNESS]+'<br/>'
17 }
18
19 $("#content").html(str)
20
21 })
22 return false
23}
Ok, so the first change is the switch from get to getJSON. This just tells jQuery to go ahead and expect JSON and turn it into a native JavaScript object for me. At that point I wasn't sure what to do. Where do I turn when I want to just... play/test/etc with JavaScript? Firebug. I ran this:
So I could look at the result. The result had 2 keys: COLUMNS and DATA. COLUMNS was an array of column names. DATA was an array of data (big surprise there). I realized that the first column in the COLUMNS array matched the first column of data. So if I wanted the person column, I could either hard code the value 0, or, do what I did here, which is to create an object that stored the column name and the corresponding position.
I then create my string. Notice how I make use of columnMap to address the data in the array. Once done, I then simply place the HTML in the div.
You can see this in action here: http://www.coldfusionjedi.com/demos/jquerycfquery/test2.html
Enjoy!


function loadQuery() {
$.get('data.cfm',{},function(data){
$("#content").html(data)
})
return false
}
to:
$("#content").load('data.cfm');
The load() method basically handles the AJAX operation and the injection of the response into the DOM for you.
If you retrieve that data via a cfc call can you use a mapping in the get or getJSON function's first argument
$.getJSON('/myAppLevelMapping/myPackage/allUsers.cfc',{method : "getUsers"}},function(data)
is the syntax used here correct for referencing the method/path? what does the syntax look like for passing in arguments to the cfc.
Once i can retrieve the data from the cfc one other task I would like to be able to do with the returned data is to return data into the table with proper column headers (change the table's column name from UserName into something like User Name easily. Ideally it would be great to be able to reference another query that stores a reference of a column name to a column display label and as it is looping through the json use the proper display label. (i guess in my query i could write it to say
SELECT UserName as User_Name FROM users WHERE 0=0
and then in my loop i guess i could do a split on the _ as a delimiter.
Any ideas on how to be accomplish this would be awesome. Thanks again for this code it will help out a lot.
http://jcfc.riaforge.org/
Invoking CFC methods via JavaScript, pretty nice. Although, personally I hate formatting result sets with JavaScript. Isn't there a better way to do this, like using some kind of template or something? Otherwise, the only practical use of returning JSON structures to JavaScript I can see is things like populating select boxes.
One really interesting part of the code sample is that 3 out of 4 of Raymond's friends are named Scott.
jCFC simplifies all of your jQuery CFC calls to a tight, easy-to-read syntax like this:
$.cfc( 'cfcName', 'method', { arguments }, { callback } );
It handles everything else, including JSON deserialization of the results, invisibly for you.
Instead of a file path to the cfc, you pass it a dot-delimited-path without the .cfc extension, which coincidentally lets you leverage mappings the way that Tim mentioned wanting to.
One really cool thing you can do with jCFC is to design your HTML interface, and then pop out the parts that change (the TR cells of a table of search results for example) into a CFC method and then just make a call like this to have live updating:
onKeyUp = $.cfc( 'cfcName', 'returnTRResults', grabFormValues( ), function( results ){ $.('#table').html( results ); });
1) Yes, I believe that would work, but normally I'd do it in the url, '.../some.cfc?method=getUsers'. Technically method is one more argument, but it is a special argument when calling CFCs.
2) To pass in more args, add more crap to the {} block:
{foo:'ray',zoo:'may'}
etc.
3) Your last item was real confusing to me. If you want to make column names dynamic, well, I guess you could return it. You are allowed to return anything you want in the json, including multiple queries. So you could return a query of your data, and another query for formatting informatio.
@Kit: jQuery has a Template doohicky plugin, but I've not played with it. This is one area where Adobe Spry really shines. I disagree though about your comment about JSON only being good for populating select boxes. JSON is a very good 'data' transport. It is very slim compared to XML or HTML.
One other thing I'll mention is that jCFC can do a slew of other things too, like:
Connecting to application-scoped singletons instead of files.
Connecting to application-scoped UDFs.
Configurationless proxy objects, in case you like this syntax:
var myProx = $.cfc( 'User' );
myProxy.backflip( );
It's worth downloading and reading through the documentation PDF which gives you a quick feel for what it can do.
1. It uses a proxy .cfc not .cfm
2. Typo. Corrected:
var myProxy = $.cfc( 'User' );
myProxy.backflip( );
When accessing jQuery dynamically using Google's Ajax API, you must use google.setOnLoadCallback() instead of the venerable jQuery(document).ready() function to execute any code once the document's DOM has become available. That's because jQuery is now being dynamically loaded, and only by using google.setOnLoadCallback() can you reliably know when jQuery has fully loaded (including access to jQuery(document).ready()).
Thanks Ray!
The other thing was, I was trying to do a modal login screen with nyromodal plugin for jQuery. However, I couldn't get the modal to not go to the next page. I wanted the login form to stay modal. So I gave up (due to time) and went to the normal HTML route.
All samples, all the time. I am just getting into jQuery and this post couldn't have come at a better time.
Also, I'm finding that I have to click the close button (x) 2x to get the dialog and modal to disappear. First click seems to remove a layer of modality, 2nd click removes everything. I'm using FF 3.0.7. Anyone else seeing this? This happens with all modals on my browser.
http://www.christopherchin.com/blog/demos/jquery/j...
Pretty rudimentary, but you get the gist of it. Comments are appreciated. I'll be blogging about this soon.
Thanks
I use Ben's templates "plugin" for generating html content from JSON. It works really great. I'm not sure if he's released it anywhere, but the code is available on his site:
http://www.bennadel.com/blog/1393-Creating-jQuery-...
I still think a documentation of a login form would be useful.
I also think an example with the jqGrid to display the returned data would be awesome (especially if text fields can be bound to the selected value from the grid)
http://www.netgrow.com.au/files/javascript_dump.cf...
another thing that might be useful if you're debugging ajax calls is jquery's $.ajax error option. $.get and $.post don't return the error text, but using $.ajax, you can view the cf error page with this:
$.ajax({
type : 'GET'
,url : 'data2.cfm'
,success: function( data ){
dump( data );
}
,error : function( event, textStatus, errorThrown ){
$('<div/>').html( event.responseText.split(/<\/?body>/)[1] ).prependTo('body');
}
});
I was inspired by Learning jQuery pg. 129.
(function($) {
$().ajaxStart(function() {
$('#busy').slideDown();
});
$().ajaxSend(function(myEvent, request, settings) {
$('#debug').append(myEvent.type+'<br />');
$('#debug').append('readyState:'+request.readyState+'<br />');
$('#debug').append('multipart:'+request.multipart+'<br />');
$('#debug').append('type:'+settings.type+'<br />');
$('#debug').append('url:'+settings.url+'<br />');
});
$().ajaxSuccess(function(myEvent, request, settings) {
$('#debug').append(myEvent.type+'<br />');
$('#debug').append('readyState:'+request.readyState+'<br />');
$('#debug').append('status:'+request.status+'<br />');
$('#debug').append('responseText:'+request.responseText+'<br />');
$('#debug').append('type:'+settings.type+'<br />');
$('#debug').append('url:'+settings.url+'<br />');
});
$().ajaxComplete(function(myEvent, request, settings) {
$('#debug').append(myEvent.type+'<br />');
$('#debug').append('readyState:'+request.readyState+'<br />');
$('#debug').append('multipart:'+request.multipart+'<br />');
$('#debug').append('status:'+request.status+'<br />');
$('#debug').append('type:'+settings.type+'<br />');
$('#debug').append('url:'+settings.url+'<br />');
});
$().ajaxStop(function() {
$('#busy').slideUp("slow");
});
$().ajaxError(function(myEvent, request, settings, thrownError) {
$('#debug').append(myEvent.type+'<br />');
$('#debug').append('readyState:'+request.readyState+'<br />');
$('#debug').append('multipart:'+request.multipart+'<br />');
$('#debug').append('status:'+request.status+'<br />');
$('#debug').append('type:'+settings.type+'<br />');
$('#debug').append('url:'+settings.url+'<br />');
});
})(jQuery);
@Ray - I was going to mention something about Spry being a great framework for formatting AJAX data with templates, but I thought it was a bit of an offshoot in a jQuery thread. In hindsight, it may have been relevant.
@Francois - seeing Ben's utilization of a TEXTAREA for templates is great, but it made me think about loading templates dynamically. I guess that over-complicates things, two AJAX requests for each call. Have you seen anything like this done well before?
I was actually just getting started with CF towards the CF8 beta, so I'm not really sure. My guess would be it uses some 8-only syntax ( ++ maybe? ) and the JSON handling and returnFormat="JSON" functionality, which could be handled inside of the single method of jCFC.cfc in 7. Let me know if you end up getting it work on 7 and I'll update the source.
@Kit:
Well, in a way it does feel very hacky. The primary reason you'd want to concatenate strings to generate HTML is optimization. Generating the interface on the client instead of server, offloading that work to a browser and minimizing your transfer size.
As a note, you can easily author the html normally as you would in a .cfm file and plug it into a cfsavecontent in a cfc method to get the same effect. You can also easily write a single CFC dynamic content distributor method that just takes a URL argument and will cfinclude and return the .cfm files you want and letting you leave them as .cfms while still able to take full advantage of the simplicity and rapid development of jCFC.
I get:
Line: 13
Character: 11149
Code: 0
Error Message: Object required
A question: how would i execute the code when a user changes a select form object instead of a click like in your example.
On the top example, once the CFM page results are placed into the div tag is it part of the page and you can call more jQuery against it's contents?
For example I want to make a page that a user selects a product via a drop down box.
I run jquery to go get all of that products colors and place them in the color picker DIV.
Now i want the user to choose a color and hide the color picker DIV and show what color the user picked in another div.
Then add the item to their shopping cart.
Doable?
[Add Comment] [Subscribe to Comments]