The ColdFusion 8 AJAX Components Debate

A debate rages on across the ColdFusion development community about the inclusion, and use, of the AJAX driven components and accompanying tags that have been included in the Beta Release of ColdFusion 8. Many examples of their use and benefit have already been posted by the likes of Ray Camden, Ben Nadel, and Ben Forta. No surprise there, as they all are huge proponents of the product, and, like so many of us, are very excited about the upcoming release of our favorite web programming platform.

But there are others still that think that the inclusion of these tags and components don't necessarily belong in the core language set of CFML. Many of these folks are also diehard JavaScripters, who took up writing AJAX early in it's infancy, fashioned their own components, or even contribute to open source libraries like JQuery. They argue that maybe the tags should have been separate CFCs available through the Adobe Developer's Exchange, or that the JavaScript rendered by the ColdFusion engine is too fat, taking up unnecessary bandwidth.

Can't we all just get along?

[More]

My First ExtJS DataGrid Pt 6: The Grid

Alright, rolling right along. Last tutorial (see the bottom of this post for a complete listing) we covered the initial setup of our ColumnModel, which is telling our DataGrid what the basic layout of our grid columns will be and to which fields of our DataStore each column will be mapped to. Now it's time to actually instantiate our grid.

So, the first thing we have to do is create our Grid object and tell it which html element will be our grid within our page. Basically we'll tell the function the ID of the div element, what DataStore object to use, and which ColumnModel object to use.

view plain print about
1// create the editor grid
2var grid = new Ext.grid.Grid('topic-grid', {
3 ds: ds,
4 cm: cm
5 });

This is it in it's most basic form. We're going to stay away from any fancy stuff for now, and get to selection models and stuff in a later post. Let's add to it a little bit by stating that the grid may be resizable.

view plain print about
1// make the grid resizable, do before render for better performance
2var rz = new Ext.Resizable('topic-grid', {
3    wrap:true,
4    minHeight:100,
5    pinned:true,
6    handles: 's'
7});
8rz.on('resize', grid.autoSize, grid);

That will make the grid resizable, and should be declared prior to rendering the grid. Rendering the grid is our next step, and way simple.

view plain print about
1// render it
2grid.render();

Can't get much easier than that. Going back to the resizable for a second, don't ask, I don't know. Easiest one for me to figure on sight is the minHeight attribute, but I haven't reviewed the API enough to know what all is going on. If you figure it out before I do then leave a comment. Next we'll need to add the paging tool bar to the footer. We'll get the footer, then add the paging toolbar.

view plain print about
1var gridFoot = grid.getView().getFooterPanel(true);
2
3// add a paging toolbar to the grid's footer
4var paging = new Ext.PagingToolbar(gridFoot, ds, {
5 pageSize: 25,
6 displayInfo: true,
7 displayMsg: 'Displaying users {0} - {1} of {2}',
8 emptyMsg: "No users to display"
9});

Notice the arguments of the PagingToolbar() function, the footer object, the DataStore object, and a JSON object with attributes of the pageSize (number of records), whether to display data set info, the message of the count, and a message to display should no records be returned.

The final step here is to load the DataStore. Once this is done you will have a complete, basic DataGrid for display.

view plain print about
1// trigger the data store load
2ds.load({params:{start: 0, limit: 25}});

Notice here the 'params'. These are name/value pairs that are passed, via post, whenever you request the next page of your data, with these values being your initial request (starting at row 0, returning 25 records). If you go back and look at your pagingService.cfm (included in the download) you'll see where these values are used.

So, that's the end of this post. You now have a basic DataGrid. In our next tutorial we'll start to style some things, and show you how to implement a custom 'renderer' for a specific column's data.

Scorpio Tour Nashville: Quick Check In

Just a quick check in. Ben's presentation was 3 hours long, chock full of Scorpio goodness! I have a ton of notes, with quick outlines of all of the features discussed. There were tons of great questions from around the room, and Ben had answers for nearly everything. Tomorrow I'll wrap all of it together in a new post.

[More]

Scorpio Tour: Nashville CFUG

Tomorrow (May 9th) is the big day! Ben Forta will begin his Scorpio presentation at 7PM at Dave Ramsey's Financial Peace Plaza (address below). The buzz just keeps getting bigger, and the signups have been coming in. We'll be raffling off a license for Scorpio, to be given after release, and a copy of Flex Builder with Charting, but you must be registered and in attendance to win. But, there's more!

The Lampo Group (Dave Ramsey) will be supplying some great food from Lenny's. And, to top it all off, everyone will receive a copy of Dave's latest book "The Total Money Makeover." Plus all of the great Scorpio swag!

BTW, we did mention that Ben is speaking about Scorpio, right! The coolest, slickest, fastest, most feature rich version of the ColdFusion server ever released! The list of new features continues to grow, with something new being announced at every stop so far. What's in store for Nashville? You,ll have to come and see! If you haven't already the register today!

Date/Time
Wednesday, 9 May, 2007, 7PM Central Daylight Saving Time

Location
Dave Ramsey's Financial Peace Plaza
1749 Mallory Lane
Brentwood, TN 37067

Scorpio Tour: Nashville

Ben's visit is quickly approaching, and every stop on the tour (so far) he's announced another exciting new feature in our favorite platform. Aaron came out of his office today to announce that the giveaways are getting even bigger. Aside from raffling off a Scorpio license (to be given upon release), we'll also be giving away a copy of Flex Builder with Charting!

[More]

My First ExtJS DataGrid Pt 3: A Paging Query

OK, we're cooking with crisco now. You've probably taken a little time to look through the examples a little bit by now, and you've seen a little of what the paging grid looks like and can do, along with the many other examples. Our last tutorial covered setting things up, but before we dive into the JavaScript we'll need some data.

Now, the paging example that's included with the Ext download calls an external PHP page to retrieve the necessary JSON dataset. JSON is great, being small and lightweight, but I'm working with MS SQL at work, which can return XML data. Since the library has built in proxies for dealing with either, I change it up to take in the XML.

Each database has different ways of writing a 'paging' query. MySQL makes it really easy by providing multiple arguments for the LIMIT statement. MS SQL makes it a little harder. See, the trick is to only pull in the records, on each db call, that you actually need. Some people pull the entire recordset and then use a query-of-query to poll their required data, but if you're dealing with very large datasets then it makes more sense to only pull what your need when the time comes. I found a great article on MSDN (which I can no longer find) that gives a good suggestion on how to approach this, by using multiple sub select statements. But, the first thing we'll do is define some default parameters for those that will eventually be passed in on the AJAX calls.

view plain print about
1<cfparam name="URL.start" default="0" />
2<cfparam name="FORM.start" default="#URL.start#" />
3<cfparam name="URL.limit" default="25" />
4<cfparam name="FORM.limit" default="#URL.limit#" />
5<cfparam name="URL.dir" default="DESC" />
6<cfparam name="FORM.dir" default="#URL.dir#">
7<cfparam name="URL.sort" default="vcLastName" />
8<cfparam name="FORM.sort" default="#URL.sort#" />

First thing you probably noticed is that I have a FORM scoped variable that matches every URL scoped variable, defaulting the URL var first then defaulting the FORM var to the URL var's value. What this allows me to do is testing. I can call the page without any additional info and it will properly run, since I have defaulted all values, and I can tag on query string variables for initial output testing, or tap it directly from a form post. These variables are pretty basic: 'start' is the starting record row, 'limit' is the number of records to be returned, 'dir' is the sort order, and 'sort' is the column to sort on. After this we move to the query itself.

view plain print about
1SELECT    (SELECT COUNT(ID) AS recCount FROM tblUsers) AS recCount,
2            ID,
3            vcFirstName,
4            vcLastName,
5            bIsAdministrator,
6            bIsActive,
7            tsDateLastLogin
8    FROM ( SELECT TOP #FORM.limit# ID,
9                    vcFirstName,
10                    vcLastName,
11                    bIsAdministrator,
12                    bIsActive,
13                    tsDateLastLogin
14            FROM (SELECT TOP #FORM.start + FORM.limit# ID,
15                            vcFirstName,
16                            vcLastName,
17                            bIsAdministrator,
18                            bIsActive,
19                            tsDateLastLogin
20                 FROM (SELECT TOP #FORM.start + FORM.limit# ID,
21                                vcFirstName,
22                                vcLastName,
23                                bIsAdministrator,
24                                bIsActive,
25                                tsDateLastLogin
26                        FROM tblUsers AS T1
27                        WHERE tsDateLastLogin IS NOT NULL
28                 ORDER BY #FORM.sort# ) AS T2
29             WHERE tsDateLastLogin IS NOT NULL
30                    ORDER BY #FORM.sort# DESC ) AS T3
31            WHERE tsDateLastLogin IS NOT NULL) AS T4
32    WHERE tsDateLastLogin IS NOT NULL
33    ORDER BY #FORM.sort# #FORM.dir#
34    FOR        XML AUTO, ELEMENTS

Notice a few things here. I only call the columns that I need. The two inner most sub selects use the TOP functionality to retrieve the 'start' row number plus the 'limit', so if you 'limit' yourself to 25 records and you are now calling page 3 (which would start with row 50) then you would say in these statements 'retrieve the TOP 50+25 rows', with the first sub-select then only asking for the 'limit' of the TOP 25. This gives you the TOP 25 rows of 50+25. You also see that a COUNT was added to the first select. Although this number appears in each record as 'recCount', it also gives you the total number of records that could be returned, thereby giving us the ability to say 'these are rows 50 thru 75 out of 38,543 records.'

If you cfdump the query return you will see multiple query rows returned, but nothing like you might expect. We now have to convert the returned query into a properly formated XML string. For this I use a function that Andrew Powell showed us in a Spry presentation that he did for the Nashville ColdFusion User Group. This was something that one of his compadres at Universal Mind wrote, and that I've adjusted slightly here.

view plain print about
1<cffunction name="sqlXMLtoCFXML" access="public" output="false" returntype="any">
2    <cfargument name="doc" type="string" required="false" default="xml" />
3    <cfargument name="qry" type="query" required="true" />
4    <cfscript>
5        var x = "";
6        var y = "";
7        var retXML = "";
8        x = listFirst(ARGUMENTS.qry.columnList);
9        for (y=1;y lte ARGUMENTS.qry.recordCount;y=y+1){
10            retXML = retXML & ARGUMENTS.qry[x][y];
11        }
12        retXML = "<" & ARGUMENTS.doc & ">" & retXML & "</" & ARGUMENTS.doc & ">";
13    
</cfscript>
14    <cfreturn retXML />
15</cffunction>

Basically this will take your MS SQL query output and format it into a proper XML document, with the ability for you to also define the 'root' element (doc). I keep this function in a utility library so that I can call it at anytime. I then take the return of this and output it between some cfcontent tags with a type of 'text/xml' to get a dynamic xml doc to be consumed by these AJAX calls.

view plain print about
1<cfcontent type="text/xml"><cfoutput>#sqlXMLtoCFXML(VARIABLES.qryReturned)#</cfoutput></cfcontent>

The Ext library makes the call to the pages via a form post, then inspects the XML return to map fields to their assigned grid columns.

But, that's another lesson. This wraps it up for today. Tune in next time (same Bat-time, same Bat-channel) for our next installment: Defining the DataStore.

P.S. Sample files will be added to this post sometime tomorrow.

The sample files are now included in the download area below. Let me know if you have any questions, comments, or war stories.

Nashville CFUG News: The Scorpio Tour

You may notice the new Flash banner above, retelling the exciting news that Ben Forta is coming to Nashville on May the 9th. With reports coming in after the first week of this tour, we are all getting pretty jazzed. Daily reports come in on new features, functions, capabilities that are going to blow the doors off the other guys. Truly great stuff, and we'll have quite a few really nice giveaways as well.

We were discussing this at last night's meeting. Which rocked! Andy Matthews (who sits next to me daily at work) did a great presentation on Cascading Style Sheets. I'm already very familiar with CSS, but Andy taught me one or two things last night. Very in depth, and well done on his first presentation effort. You can access the Adobe Connect preso from the link in the Archive section of the Nashville ColdFusion User Group website.

So, anyway. Scorpio is coming. It's weeks away now, so make sure to go to the UG site and signup. For those who might be unfamiliar (or slightly familiar), Ben is a terrific technical author, with books on ColdFusion, SQL, MySQL, and more, and is a senior technology evangelist for Adobe. Not to mention his alter ego, Scorpio Man.

The Current ColdFusion Job Market

I found myself, again, at a crossroads. Recently I decided to update my resume. I had accounts on Dice, Monster, CareerBuilder, and ComputerJobs from my last job search, so I decided it couldn't hurt to keep them up to date. I had been in my current position for sixteen months, learned a few things, accomplished various goals, and thought it would be a good idea.

[More]

Tools Make Life Easier

I am a huge fan of things that make my life easier, and love tools that do just that. It's kind of like moving from writing my thoughts down on paper to using a computer, I still (try to) write quality content, but it's not nearly as time consuming now. I can write, read over, rewrite a piece over and over agian, without wasting a load of paper, correcting seven million spelling mistakes, or emptying a white-out bottle.

Tools are those things that you use to get a job done, and there are almost as many tools as there are jobs. Tools are those wonderful things that separated man from animal. Funny thing about tools, though, not every tool will handle every job. You have to try them out, take 'em for a test spin, work out the kinks, and see what works best for your development style.

Once I got past the learning curve, Model Glue: Unity turned into a natural flow of MVC development, ColdSpring has assisted me immensely in managing my object dependencies, and Reactor's scaffolding has slimmed down the gruntwork of creating my CRUD methods. This is part of the job of frameworks, to make our lives easier. CFLib and the ColdFusion Cookbook are repositories of experienced knowledge, condensed into freely usable bits of logic. RIAForge takes it to a whole other level, by providing us with entire applications. All of these are tools for making our lives easier. (How many times was Ray indirectly referenced there?) But, it's important to not become married to any one toolset, which is why I keep my nose in Mach II and Fusebox, have started checking into Transfer, and really like the simple flexibility of tools like DataMgr and AjaxCFC. You never know what the next project might call for.

The ColdFusion community has progressed leaps and bounds in the seven years I have been a part of it. As a language, CFML has added constructs to utilize object oriented design patterns, create dynamic reports in a variety of distributable formats, and given us the ability to create server event driven functions, just to name a few of the changes. Open Source projects are all over the place, the server is used in a majority of Fortune 100 companies, the government (of all industries) has adopted this 'expensive' platform like gangbusters, and demand for experienced developers is through the roof.

And when Scorpio gets released the 'other guys' won't know what hit 'em.

So, open up CFEclipse, use Subclipse to checkout some of the wild goodness from their respective repositiories, and start exploring. Take a deep look into their core files (but, don't change 'em!) for some insight into the style of some of the masters of our industry, and look forward to a very bright future. ColdFusion has helped take the guess work out of some complex tasks, and it's only getting better. And easier!

Feedback Request: Indenting Code

OK, I'm looking for feedback from the community at large. In a recent development meeting one of our new developers made the following (paraphrased) comment about cleaning up existing code:

I'd like to, when we can, rewrite a lot our display code. There are a lot of unnecessary tabs and spaces. With several thousand open sessions, this is a lot of unnecessary data being transmitted back to the user, chewing up our bandwidth. I like to keep my opening and closing tags on the same line, most of the time, and eliminate the unneeded space.

While I can see the argument he is trying to make, I personally disagree. First of all, we have a large legacy codebase, with heavily nested table layouts. While I can see replacing tables for non-tabular data, I think the indented code makes it much easier to read, adjust, and maintain. I do the same for most block level elements. And, I absolutely use it within the programmatic (ColdFusion, ActionScript, JavaScript, etc.) code. I believe in whitespace suppression (enablecfoutputonly="true"), but I don't agree with eliminating readability.

Am I the only developer who sees the value of indenting their code? Or, am I just holding on to archaic coding practices pushed upon me by some professor or another? Does my gain (maintainability/readability) outweigh the overhead implied? What are your thoughts?

Previous Entries / More Entries