ColdBox 2.6 + AJAX (powered by jQuery) = Sinfully Easy
Posted on May 16, 2008 at 4:48 PM in ColdBox, ColdFusion, jQuery
I've mentioned before that I <3 ColdBox and that I <3 jQuery. Independently of one another, they are just a pleasure to work with. Today I decided to write my first-ever jQuery-powered AJAX functionality inside a ColdBox-powered application. It's ridiculously simple to do - one might even say sinful. So easy in fact, that I decided to post a quick "tutorial" on how to handle a pretty common task with ColdBox and jQuery.
The Task: Browse a User List
Pretty much any decent-size application has a user list. When the list of users gets really big, most people add some sort of functionality to the interface that allows the list to be sorted by the first letter of the last name or sometimes even the first name. It might look something like this:
Typically speaking, when you click on whichever letter you want to sort by, a brand new page will be loaded, and the sorting will be done by passing the letter to the application server in the querystring, then passed on to the database server to retrieve the appropriate records. I like to save bandwidth where I can, so I decided to update an application I'm working on and make use of a little bit of AJAX so that only the actual list is replaced/refreshed, rather than loading an entire page.
ColdBox: noLayout=true
ColdBox's setView() method has an optional argument named "noLayout". By default this argument is set to 'false'. However, for our little AJAX operation, we want to change that to 'true', because we want only our list of names to be rendered, and not the entire layout. (Remember, the layout is already on the screen, along with the default list and the alpha-select list as shown above.)
There are a couple of ways you can have ColdBox take care of this request. One way is to have separate methods; one for rendering the full page (including layout), and one for rendering only the actual list itself. Another possibility is to have a single method that handles the request, and use an "isAjax" flag to decide whether or not to render the whole layout. My personal preference is the latter, because it allows me the luxury of never messing with the HTML in the view once I've got it and the jQuery (shown below) in place. So, here is a snippet of how I handle this flag in my controller.
- if ( NOT event.getValue("isAjax", false) ) {
- event.setView("nameSelect");
- } else {
- event.setView("nameSelect", true);
- }
The first line determines if 'isAjax' is false, which is set to be the default value. If it is false, then I set the view without providing the "noLayout" argument, which as we noted above defaults to false. However, if 'isAjax' is true, I set the view and supply a value of true to the "noLayout" argument.
That is all that is required! We're now done with the ColdBox half of our update! Schweeeeeet!
jQuery: The Beauty of Unobtrusive JavaScript
For years I shied away from using JavaScript in my applications. There were two things about it that I just absolutely hated:
- Mucking up my HTML with JavaScript code
- The ease with which a user can disable or otherwise get around it, which would break the application (for that user)
Then I found jQuery. Now I can write a comparatively small bit of code, and I can leave my (x)HTML alone to do what it is supposed to do. Our little alpha-sort list is no different. I'm not going to touch the HTML at all. This way, if the browser does not support JavaScript (or it is disabled), the application still works perfectly fine. However, if JavaScript is supported, we get the bonus of using far less bandwidth and execution time. So, without further ado, here is our quick and dirty jQuery:
- $(document).ready(function() {
- $("a.select-letter").click(function() {
- var theURL = $(this).attr("href")+"&isAjax=1";
- var thisL = $(this).attr("class");
- var thisL2 = "";
- // start the 'loading' image
- $("#ajax-load").removeClass("hide");
- $("a.select-letter").each(function() {
- thisL2 = $(this).attr("class");
- if ( thisL2 != thisL ) {
- $(this).removeClass("current-letter");
- } else {
- $(this).addClass("current-letter");
- }
- });
- $.get(theURL, {}, function(data) {
- $("#nameSelect").html(data);
- });
- $("#ajax-load").addClass("hide");
- return false;
- });
- });
Since the purpose of this post is not to teach you the basics of jQuery, I'm merely going to highlight a couple of things that we're doing.
First, on line 3 we're grabbing the URL from the 'href' attribute of the letter that was clicked on, and we are appending our 'isAjax' flag to the querystring, setting it to true (or 1).
Next, on lines 8-15, we're removing the "current-letter" class from all of the letters that were not clicked on, and adding it to the one that the user clicked. (This is a class that highlight's the first letter of the current list. Completely optional, of course, but I like it.)
Then on lines 16-18 we're making use of jQuery's $.get() Ajax method to run our ColdBox event (request) and update the "nameSelect" div with the new list.
Lastly, on line 20, we're telling the browser "hey, don't follow the link you just clicked on", because we've already handled the request via Ajax.
Summary
It's that easy. Sinful. Delightful. I so totally <3 ColdBox + jQuery. :-)
Latest Articles
- No recent entries.
Categories
- ColdBox (21) [RSS]
- ColdFusion (92) [RSS]
- Fusebox (3) [RSS]
- General (22) [RSS]
- jQuery (15) [RSS]
- Kalendar (1) [RSS]
- Linux (1) [RSS]
- Mura CMS (1) [RSS]
- Railo (1) [RSS]
- Rants (5) [RSS]
- Transfer (8) [RSS]
- Uni-Form Tag Library (36) [RSS]
Quick Links
Blogs I Read
Calendar
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
« Feb | ||||||
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Subscribe
Enter a valid email address.
On 5/16/08 at 6:56 PM, Jason Durham said:
On 5/16/08 at 9:20 PM, Sana said:
@Jason you are welcome to ask million question.. just only one million.. LOL
On 5/20/08 at 9:11 AM, Tony Garcia said:
It might have been better if the attribute was 'Layout' instead of 'noLayout', because 'layout="true"' would be more intuitive as the default behavior instead of the double-negative 'noLayout="false"'.
On 5/20/08 at 1:26 PM, Matt Quackenbush said:
@ Sana - I'm interested in hearing more about what you have in mind. Shoot me an email and we can discuss your idea(s).
@ Tony - Nice catch. Thank you. Obviously I knew that, but said it backwards. I do that way too often. I updated the post so that it now reads correctly. ;-)
On 7/8/08 at 9:17 PM, Matt Quackenbush said:
event.setView("viewName", event.getValue("isAjax", false));
On 3/10/09 at 2:18 PM, Brad Wood said:
Now I'm wondering if I _shouldn't_ be using the proxy if the result of the event is immediately usable without additional massaging.
I am using jQuery, but not for my ajax calls. I have been using cfajaxproxy for that those.
Thoughts?
On 3/10/09 at 6:53 PM, Matt Quackenbush said:
1) I am taking full advantage of ColdBox's event mechanisms, and therefore I have everything available to me just as I would in a synchronous request, and
2) I am using Ajax only if JavaScript is enabled, so the event exists whether or not Ajax is involved. Since I abhor code duplication, I just use a single event to handle two use cases.
In this particular example the return value is simple HTML, but even in cases where I need a JSON response, I still generally use a "normal" event call and use event.renderData(type:"JSON"). Again, for the same reason as #1 above (and sometimes #2).
RE: cfajaxproxy. I know that I'll be considered a blasphemer for this, but I don't use anything from CF that loads JavaScript, period. It is always extremely bloated, and extremely outdated, and quite frankly, I don't believe that it belongs in the Application Server. If I need Ajax functionality, I write it myself. "Write it myself" used to mean write it from the ground up. Thankfully I found jQuery and so it now just means write the little bit I need to write on top of jQuery to get the job done. :-)
Now then, ColdBox now has an ajaxproxy.cfc that you can utilize for your Ajax calls. I don't think it existed at the time I wrote this post, but that's been nearly a year ago, and I've slept since then, so I can't be certain of that. Anyways, I haven't used it myself, but a lot of people are using it with fantastic results, so that might be something you'll want to take a look at.
Sorry for the book response. Hope it helps nonetheless. ;-)
On 3/11/09 at 1:59 AM, Brad Wood said:
There's something I don't like about having if statemtents in my handlers that make the events have to "know" how their called (isAjax). I like the anonimity that the proxy provides so my events don't have to
care how they are being called. That being said, I also abhor writing anything twice and adding extra layers that don't do anything.
I didn't know about the event.renderData() method yet, so that is kind of cool.
Would you personally ever recommend using the Coldbox Proxy?
On 3/11/09 at 2:10 AM, Matt Quackenbush said:
RE: ColdBox Proxy. I can't really "recommend" something that I've not yet personally used, but I certainly have no reason whatsoever to recommend against it. I think it all depends on what the use case is, and the methodologies employed in building one's applications. If one were to build a front-end (UI) heavy application that used lots of Ajax loads, I'd probably be quite inclined to use it. But again, I certainly have no reason to say not to use it. ;-)