Chapter 15. Beyond HTML Forms: ColdFusion-Powered Ajax

You’ve used HTML forms extensively in the past few chapters, and forms will undoubtedly play an important role in all of the applications you build. HTML forms are easy to create and work with, but they are also very limited and not overly capable.

For example, HTML form controls lack commonly needed controls such as date choosers and data grids. They lack any real form field validation, as discussed previously. They also are also essentially bound to the page request model of the Web: every change requires a roundtrip back to the server and a subsequent page refresh.

HTML forms leave much to be desired, and Web developers have acquired something of a love-hate relationship with forms, appreciating their simplicity but despising the lack of functionality that this simplicity causes.

To get around these problems and limitations, ColdFusion has constantly sought new and innovative technologies to include with the product for you to use. From Java applets to Adobe Flash controls to XForms abstractions, as new options become available, ColdFusion tries to take advantage of them.

ColdFusion 8 and 9 continue this pattern with powerful new HTML controls and with simplified Ajax support. This chapter explores these new options.

Note

Coverage of XForms and Adobe Flash forms are beyond the scope of this book and are thus not discussed in this chapter.

Using the Extended Controls

An example provides the best introduction to ColdFusion’s extended form controls. In Chapter 14, “Using Forms to Add or Change Data,” you created a series of forms to allow users to insert and update movie data in the Films table. One of those fields was a date field that required users to enter a valid movie release date.

Asking users to enter dates is always asking for trouble. Some users will enter digits for months and others will spell out or abbreviate months, some users will enter two-digit years and others will enter four-digit years, some users will enter hyphens as separators and others will use slashes—you get the idea. Rather than asking the user to enter a date manually, you really need a date control: a pop-up calendar that lets users browse months and click desired dates. But, as already noted, there is no date control in HTML forms.

Fortunately, there is one in <cfform>, and it does exactly what we want. To create a date field, all you need to do is use <cfinput> and change type to type="datefield"—it’s that simple.

Listing 15.1 is an updated insert form (based on the one created in Chapter 14); Figure 15.1 shows the new form.

Listing 15.1 insert1.cfm—New Movie Form

image

image

image

image

image

Figure 15.1 ColdFusion offers enhanced form controls, including a rich text editor and a date field.

image

Most of Listing 15.1 should be self-explanatory by now. A <cfquery> is used to retrieve ratings to be used in a subsequent <cfselect> control, and <cfform> is used to create the actual form. The DateInTheaters field is now of type type="datefield", which creates the nice pop-up date field seen in Figure 15.1.

I also stuck another goodie in the code without telling you. The <cftextarea> box is no longer a simple text control; it is now an actual editor that lets you highlight text to make it bold, and so on. To use this feature, all you need to do is add richtext="true" to the <cftextarea> tag.

The real beauty of these controls is that they work as-is—no plug-ins are needed, and they have no special browser requirements. All current browsers on all major operating systems are supported.

Note

The rich text control is highly configurable, providing full control over the toolbars and buttons as well as the color schemes (via skins). In this example, the Basic toolbar was used. The other built-in toolbar is Default, and it contains several rows of buttons (far more than we need here). You can also create custom toolbars if necessary. Consult the ColdFusion documentation for information on creating and modifying toolbars.

ColdFusion Extended Form Controls

You’ve seen examples of two of ColdFusion’s extended form controls. But what other control types are supported? Table 15.1 lists the form controls along with their CFML syntax and usage notes (and notes those that support Ajax use, which will be described later in this chapter).

Table 15.1 Extended Forms Controls

image

You’ve already seen examples of the date field and rich text editor; let’s look at a few more controls.

The <cfgrid> control is used to create data grids: two-dimensional spreadsheet–type views of data as shown in Figure 15.2.

Figure 15.2 ColdFusion’s data grid makes it easy to display multiple rows in a scrollable grid.

image

Listing 15.2 contains the code that created the grid shown in Figure 15.2.

Listing 15.2 grid1.cfm—Basic Data Grid

image

Listing 15.2 invokes the list method in movies.cfc to obtain a list of movies. It then creates a data grid using <cfgrid>, passing the query to it.

Listing 15.3 is the list method used to populate the grid.

Listing 15.3 List Method

image

This is all it takes to populate a data grid. Data in the grid can be sorted by clicking column headers (click once to sort in ascending order and click again to sort in descending order), and columns can be resized and moved as needed.

By default, <cfgrid> displays all of the columns in the passed query, using the column names as the grid headers. This behavior can be changed by using the <cfgridcolumn> tag, as seen in Listing 15.4, which creates an updated data grid.

Listing 15.4 grid2.cfm—Controlling the Data Grid Display

image

The updated listing explicitly prevents the FilmID column from being displayed and then provides alternate headers and widths for the other three columns.

Tip

The <cfgridcolumn> attribute also can be used to control the order in which grid columns appear.

Note

Additional <cfgridcolumn> attributes enable control of fonts, colors, and much more.

Another useful control, one that does not exist in HTML itself, is the auto-suggest control. This is actually less a control and more a change to the way that text input controls usually work.

Imagine that you have a form that prompts the user to enter an address. There are lots of possible options for the City field, but if you have lots of city names already stored in your database tables, you can assist the user by providing a drop-down list of suggestions (which the user can select or just ignore). This type of control is called an auto-suggest control, and it usually pops up only if the user pauses, giving you the opportunity to suggest text options.

There is no auto-suggest control in HTML. Creating an auto-suggest control requires writing some pretty sophisticated JavaScript—unless you are using ColdFusion, that is, in which case you don’t have to write any JavaScript at all.

To turn <cfinput type="text"> into an auto-suggest control, all you need to do is provide the suggestions. For example, the following code creates an auto-suggest control:

image

If you were to save and run this code, you would see a regular text input control. But if you typed the letter L and paused, you’d see a pop-up box containing the two options that begin with the letter L.

Of course, the list need not be hard-coded. Listing 15.5 contains a complete auto-suggest example that creates the screen shown in Figure 15.3.

Listing 15.5 autosuggest1.cfm—Basic Auto-Suggest

image

image

Figure 15.3 Auto-suggest lists can be hard-coded and populated programmatically.

image

The code in Listing 15.5 gets a list of ratings using <cfquery>. Auto-suggest values need to be passed as a comma-delimited list, and so a list is constructed using the ValueList() function, which takes the name of a query column and returns a comma-delimited list of all of the values in that column. That list is then passed to <cfinput> as autosuggest="#list#".

Note

All of the controls discussed here use JavaScript internally and require that JavaScript be enabled in the browser. If you view the source code on the generated page, you’ll see the JavaScript that is included and generated.

Working with Ajax

All of the controls used thus far have embedded data (queries, lists, and so on) inside of the controls themselves. That works in many situations, but consider the following scenarios.

What if your auto-suggest values are being populated by a table that contains thousands of entries? You don’t want to load all of these entries into a list in the control itself. For starters, that will increase the page size significantly and seriously affect performance, but also, you don’t want to show your user that many options. What you really want is no data at all in the auto-suggest control; when the user types some text and pauses, you want your application to send that text to ColdFusion, which then returns the relevant auto-suggest entries. And of course, you want this process to work without refreshing the page.

Or suppose that the data grid we created previously displayed all of the movies at once. This is fine here, because our table contains only 23 movies. But what if the database table had hundreds or even thousands of entries? You wouldn’t want them all displayed at once. Instead, you to show a page of data at a time, allowing users to scroll back and forth as needed. And of course, this process too would have to work without refreshing the page.

Is this doable?

The answer is yes, and this is where Ajax comes into play. Ajax (which stands for Asynchronous JavaScript and XML) is not a product or a technology. Actually, it’s not any single thing you can point to. Rather, it is a technique that combines DHTML and JavaScript with the capability of Web browsers to make asynchronous HTTP calls.

If that sounds obscure, don’t worry. What it simply means is that JavaScript (the scripting language supported by just about every Web browser) has the capability to issue Web page requests under programmatic control—requests that don’t actually update or refresh the screen. By coupling that capability with some clever JavaScript and DHTML, you can make Web browsers do some very interesting things, including addressing the scenarios just mentioned.

→ Ajax, and indeed ColdFusion’s Ajax support, cannot be covered fully in one introductory chapter. In this chapter, you learn the basics; for more information, see Chapter 30, “Advanced ColdFusion-Powered Ajax,” in Adobe ColdFusion 9 Web Application Construction Kit, Volume 2: Application Development.

Chapter 11, “The Basics of Structured Development,” introduced ColdFusion Components (which we have been using ever since). Well, ColdFusion Components are the key to the way that ColdFusion’s Ajax controls work. As just explained, Ajax controls make calls back to the server as needed, and in ColdFusion those calls are to CFCs.

Let’s revisit the auto-suggest example, this time using an Ajax auto-suggest control. First we’ll look at the CFC method needed to power the control. Listing 15.6 shows the code.

Listing 15.6 lookupMovie Method

image

Most of the code in Listing 15.6 is code you have seen before, but there are some very important points to note here. First, the method contains an attribute of access="remote". Usually, CFC methods can be invoked only by other ColdFusion code running on the same server, but a CFC method that needs to be invoked by a Web browser (as is the case with Ajax controls) needs to be explicitly granted that right, and that is what access="remote" does.

Note

Any CFC methods that include access="remote" can be invoked remotely, even by other users. Be very careful with the methods you expose, and pay attention to CFC security (discussed in Chapter 24, “Creating Advanced ColdFusion Components,” in Volume 2).

The lookupMovie method accepts an argument—the string the user has entered thus far—uses that text in <cfquery>, and then returns a comma-delimited list containing the matches (the format required by the auto-suggest control).

Now let’s look at the client-side code that uses a <cfinput> control that uses the lookupMovie method. Listing 15.7 contains the code, and the result is shown in Figure 15.4.

Listing 15.7 autosuggest2.cfm—Ajax Auto-Suggest

image

image

Figure 15.4 Ajax-powered auto-suggest controls retrieve their suggestions by making calls back to ColdFusion.

image

The first thing you’ll notice about Listing 15.7 is that it contains no database query and no <cfinvoke> to invoke a CFC method. Instead, we’ve added this line to the <cfinput> control:

autosuggest="cfc:movies.lookupMovie({cfautosuggestvalue})"

Unlike the example in Listing 15.5, autosuggest does not contain a list. Rather, it points to a CFC, in this case a CFC named movies (in the current folder), and a method named lookupMovie (the method in Listing 15.6). The lookupMovie method expects a string to be passed to it, the text that the user has typed thus far. Rather than requiring you to write JavaScript to extract that value, ColdFusion allows you to refer to a special client-side variable named cfautosuggestvalue, which will automatically be replaced by the actual value entered by the user when the CFC method is invoked. The cfautosuggestvalue variable is enclosed within curly braces ({ and }), which ColdFusion uses to delimit expressions within client-side code (in much the same way as server-side code uses # to delimit expressions).

Note

A full path is not needed when pointing to a CFC in the current folder. To point to a CFC in another folder, a fully qualified path is needed.

Save the code and give it a try. Each time you type text and pause, an asynchronous call is made to the CFC method, data is retrieved and returned, and suggestions are made.

You’ve now created an Ajax-powered control without having to worry about what Ajax actually is and without having to write a single line of JavaScript.

And that’s why we love ColdFusion!

Let’s look at another, more complex example: a data grid that must handle any amount of data, supporting paging as needed.

Again, the solution has two parts: the CFC that actually accesses the data, and the client-side code that is bound to it. Let’s look at the CFC method first; Listing 15.8 shows the code.

Listing 15.8 lookupMovie Method

image

Listing 15.8 contains a method named browse that is used to browse through rows in a table. The browse method returns data, one page at a time, and so it has to know the page that is requested as well as the number of rows per page. That way, if there are 10 rows per page and page 3 is requested, browse will know to return rows 21 to 30, and so on. These values must be passed by the client with each request, and indeed they are the first two arguments in this method. In addition, as mentioned previously, users can sort data grid contents by clicking column headers, and so the current sort column and direction are also passed by the client (if the user sorted data).

The method then uses <cfquery> to retrieve the data, optionally appending a SQL ORDER BY clause if the user sorted data.

Finally, the ColdFusion QueryConvertForGrid() function extracts the data for the desired page and formats it as needed by <cfgrid>, and the results are returned.

The client-side code creates the <cfgrid> control that uses the browse method. Listing 15.9 contains the code, and the result is shown in Figure 15.5.

Listing 15.9 grid3.cfm—Ajax Data Grid

image

Figure 15.5 An Ajax-powered data grid supports record paging as well as on-demand sorting.

image

This <cfgrid> control is similar to the one in Listing 15.4. The big change is that the query attribute (which passes an actual query) has been replaced by a new bind attribute. The bind attribute points to a CFC method, using the same syntax as in the auto-suggest example previously. As already explained, the CFC method expects up to four arguments (the first two, current page and size, are required, and the last two, sort column and direction, are optional). Again, ColdFusion provides special variables that can be used in place of actual values: {cfgridpage} is replaced by the current page, {cfgridpagesize} is replaced by the value passed to the pagesize attribute, and so on.

All you need to do is save and run the code. To display the first page of data, JavaScript in the Web browser invokes the CFC method, obtaining the first set of rows. Then, as you browse from page to page or as you sort and resort data, that CFC method is called asynchronously, in the background, and the grid is updated.

Note

The <cfgrid> control supports data editing too, but that function is not covered in this chapter.

Using Bindings

You have already seen examples of bindings: The Ajax-powered auto-suggest control and data grids both used bindings to refer to ColdFusion Component methods on the server.

Bindings can also be used on the client side, allowing one control to refer to, and interact with, other controls. Let’s look at some basic examples.

→ For full coverage of ColdFusion Ajax bindings, refer to Chapter 30.

We’ll start with yet another data grid, but one with an interesting twist. As shown in Figure 15.6, this new data grid has a <textarea> box alongside it, so that when a movie is selected in the grid, the detailed summary is displayed in the box on the right. This type of user interface obviously requires interaction between controls, and thus it requires bindings.

Figure 15.6 Bindings allow controls to interact with other controls.

image

The CFC method that powers this new data grid is the same as the one used previously, so we won’t revisit it here. But the client-side code, shown in Listing 15.10, warrants a closer look.

Listing 15.10 browse.cfm—Ajax Data Grid

image

image

Aside from some table tags and control sizing, most of Listing 15.8 is used unchanged. The big change is the following code:

image

Here, a <cftextarea> area is created and named, and its size specified. Then bind is used to connect <cftextarea> to movieGrid.summary (the summary column in movieGrid, the data grid). This way, whenever the selection in the movieGrid data grid changes, the value in <cftextarea> is updated automatically.

Let’s look at one final example: a more complex use of bindings. We’ve used <select> controls several times, and those controls have typically been populated with data retrieved from a database.

But what if you want multiple related <select> controls? What if you want a <select> control that lists all of the movie ratings and then another <select> control that lists the movies for whatever rating was selected in the first control? Obviously this scenario requires a way to make calls to ColdFusion to obtain the ratings initially and then a way to obtain a new list of movies whenever the rating changes. An example of the desired results is shown in Figure 15.7. How can we achieve these results?

Figure 15.7 Bindings can be used to trigger asynchronous calls to ColdFusion as needed.

image

Well, if you have not figured it out yourself, the answer is to use bindings and Ajax-type asynchronous calls to ColdFusion Components.

We need two methods for this example: one to populate each of the <select> controls. Let’s look at the CFC methods, shown in Listing 15.11, first.

Listing 15.11 getRatings and getFilms Methods

image

image

As before, both methods return queries, and both are access="remote". The getRatings method does not need to accept any arguments; it simply obtains the list of ratings. The getFilms method accepts a single argument, RatingID, and then retrieves just the movies that match that rating, which are then returned. The SQL statements in both methods use a SQL Trim() function to get rid of any trailing spaces (as these could distort the display within Ajax controls).

Simple enough. But what about the client side? The code is in Listing 15.12.

Listing 15.12 selects.cfm—Related SELECT Controls

image

image

The code in Listing 15.12 contains two <cfselect> controls, both of which have a bind attribute connecting them to our two CFC methods. But there are two important differences between the controls.

The first <cfselect> control, RatingID, is simply bound to the getRatings method, and no arguments are passed (none are needed). However, getRatings would never be called because no event would force that call (unlike with the data grid used previously, which automatically requests the first page, <cfselect> bindings occur when something triggers them). This is why bindonload="true" is added; it tells the JavaScript code to trigger a server call as soon as the control is loaded, and that way the first <cfselect> control is automatically populated and ready for use. As the asynchronous server call returns a query, display and value are used to specify the columns to be used for the generated <option> tags.

The second <cfselect> control, FilmID, is bound to the getFilms method, which requires that a RatingID argument be passed to it. Thus, {RatingID} (the name of the first <cfselect> control) is passed as an argument to getFilms, and {RatingID} is replaced by the actual RatingID value when the call is made. This way, whenever the value in RatingID (the first <cfselect> control) changes, the binding on the second <cfselect> control is fired, and the list is updated—clean and simple.

And there you have it: extensions to HTML form controls that you can use as needed, and simple yet powerful Ajax functionality when that is called for.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.27.45