Creating Better Forms Faster with ColdFusion MX 7

When the ColdFusion engineering team started planning ColdFusion MX 7, we finally had time to give the cfform tags some love. We talked to and heard from many customers and knew that we needed to do a cfform tag overhaul for HTML-based forms. We also knew that that if it was possible, we wanted to help ColdFusion developers harness the richness of Macromedia Flash Player and open up the cfform tag to the incredible flexibility of XForms. We knew that if we could accomplish all of this with a simple and easy cfform tag syntax, it would be a big win for you, the developer, and your application users.

Originally, ColdFusion cfform support was just a few tags that generated some basic JavaScript validation - validation that certainly had its critics. This all changed with ColdFusion MX 7. We decided it was time to throw out the tedious approach of creating forms and breathe some new life into the cfform tag.

First we had to review the enhancement requests and bug reports for the current cfform tag to make it do what you have wanted and needed it to do since we introduced it. To achieve this, we had to rewrite old tags from scratch, update validation, add new tags, and fix a few bugs (OK, fix a lot of bugs).

After making a solid foundation, we rethought the cfform tag functionality altogether. Although this was the second step in our development process, we started this step years ago. When the merger between Allaire and Macromedia occurred, there was a lot of talk about generating Flash from ColdFusion - specifically forms. During the development of ColdFusion MX 6, there were numerous "what if" discussions about the benefits of being able to use layout managers with HTML forms, which is similar to defining forms in Java Swing applications. However, it wasn't until ColdFusion MX 7 that we were able to spend the time to do this right.

Updating the cfform Tag
As with all product development, you must start with evaluating the foundation. Thus, before we could add all sorts of cool new features to the form tags, we needed to make the foundation rock-solid. We spent the first cycle of development upgrading the cfform tags. What did this involve?

You may not know this, but some ColdFusion tags are not written in Java; they are actually written in CFML for use in your CFML pages, just like the ColdFusion custom tags you write yourself. However, the way ColdFusion custom tags associate with their parent wasn't flexible enough for the plans we had for adding XML and Flash forms support to the form tags. So, the first step was to rewrite these tags from scratch as Java tags, while at the same time adding all of the missing HTML tags that the cfform tags didn't generate. Personally I always hated that I could use cfinput to define a text field but not a submit button. One of the joys of being both a user and developer of the product: I can fix my own pet peeves.

Once we finished rewriting the new tags, we dug through the bug tracker. We knew there were numerous enhancement requests for the cfform tag that customers frequently requested through mailing lists and forums. To ensure that we didn't miss anything, we searched for all open bugs and enhancement requests submitted all the way back to ColdFusion 3 and then transferred them into the ColdFusion MX 7 queue. While reviewing all of these requests, we still decided to defer or close some of the bugs and enhancements, but we wanted to ensure that we evaluated every single open bug and enhancement. (By the way, this was a common task for most of the ColdFusion MX 7 features, not just the cfform tags.)

Evolving Form Validation
At this point, the cfform tags looked pretty good: they were a lot faster and worked a lot smoother, but something else was missing. For years, users had requested new validation types, such as e-mail and URL. There had also been many complaints about having only JavaScript validation for the client side (what if the client has JavaScript disabled?). Other complaints were about the server-side validation we supported (it required developers to use HTML hidden fields). In addition, when you used server-side validation, you couldn't validate all of the same types of data as you could with client-side JavaScript validation, which caused a frustrating discrepancy between different validations techniques.

To fix these issues, we synchronized all of the validation routines from the client-side JavaScript with the validation libraries on the server. There were a few differences we couldn't change for backwards compatibility. For instance, server-side date parsing validation allows more date formats than the client-side JavaScript validation; however, if you call e-mail validation on the client or on the server now, ColdFusion runs the same regular expression to validate it. Of course, calling these validation routines was still annoying because you still had to code an HTML hidden field to trigger each field. Although using hidden fields is still a useful way to validate data on intranets or other applications where you control who uses your application, there is a problem using hidden fields to validate data on a public site: someone could hack your site and remove the hidden fields, bypassing any validation you thought was in place. We did a few things to resolve this problem.

If you use the hidden fields, ColdFusion MX 7 automates their creation. As you may know, previously you had to code an input field and a hidden filed for server-side validation. Now you don't need to remember the cryptic syntax to trigger the validation in ColdFusion.

Before:


<cfinput type="text" name="fname"
   required="true">
	<input type="hidden" name="fname_
  required" value="Fname is required">

After: (in ColdFusion MX 7):


<cfinput type="text" name="fname"
  required="true" validateat=" 
  onServer">

You use the new validateAt="" attribute to define three different location values to validate: onSubmit (this is the default option), onBlur (a new validation location type), and onServer. You can mix and match these values or specify the validation locations you would like to use as a comma-separated list:


validateAt="onBlur,onServer"

On a ColdFusion page - especially a form action page - it is a common and best practice to validate all variables passed into the page. To make this easier for you, we added access to all server-side validation routines in the cfparam tag through the type attribute. Thus, you can verify whether the variable exists and, at the same time, validate the value as a specific data type, all in one tag (this even includes the powerful "RegEx" validation type).

Example:


<cfif isDefined("form.submit")>
     <cfparam name="form.email"
       type="email">
     <cfparam name="form.password"
       type="regex" pattern="
       [a-z]{1,3}[0-9]{6,10}">

     <!--- 
Your custom form submission logic 
  goes here 
--->
</cfif>

Because this may not work for all solutions, we didn't stop with the cfparam tag but, rather, added a new ColdFusion function, the IsValid () function as well. Use this function to call validation routines against any variable (for instance, you might want to validate against a value you query from a database).

Example:


<cfif isValid("email", myQuery.
  usersEmail)>
     <cfmail from="webmaster@mysite.
       com"
          To="#myQuery.usersEmail#"
          Subject="System Update">

          This is to inform you that
            at 2pm today ...
     </cfmail>
</cfif>

Again, we could have stopped here, because the cfform tags were now a solid tag set with plenty of new functionality. Instead, we knew that this new foundation gave us stability and an opportunity to have some fun, reinventing the way you build forms in web applications.

New Layout Managers
When building web applications, I noticed that I spent the majority of my time building forms - creating layout and user interfaces. I don't know about you, but I prefer to code the back-end logic and functionality, not the look and feel. To make matters worse, all my forms began the same way: a two-column table with the label in the left column, setting the width to 150 pixels, and a form field in the right column. It's a nice and simple form (you've built this form haven't you?). It always seemed futile to me to keep rewriting this same table again and again. The problem was, I only cared about a dozen or so form elements, not the 200-300 lines of HTML code that wrapped them.

So we started thinking, wouldn't it be cool if developers could use layout managers like they do in other languages, such as in Java Swing applications? The problem is that the web and HTML do not have layout managers; they use tables, div tags, and span tags with absolute and relative positioning - in essence, they have no automatic layout logic.

Luckily for us, many pieces came together at the same time. First, the Macromedia Flex team was working on layout managers for Flash forms based in Flex. Second, Flex is based on XML. For years we wanted to give you the ability to generate Flash from ColdFusion and give you the power of rich forms available with Flash components. With Flex, we noticed that our prototype for XML forms - based on the XForms schema -would map very easily to the MXML (the Flex markup language) we needed for Flex. This relationship allowed us to expose the same CFML syntax for the layout managers in both XML and Flash forms.

What do these layout managers mean for you? It means you now can develop forms with layout managers, giving you more time to spend on your application's functionality instead of its layout.

Even though ColdFusion MX 7 passes the job of managing the layout to the layout managers, you still cannot create forms 100% automatically. There are just too many different ways to lay out a form. As you know, when you leave it to an engine to guess what you want, things never work the way you might like and you may never use it.

The key was to find a middle ground that everyone could work with. This middle ground had to remove the bulk of code you would write to lay out a form, yet still provide a way for you to define some layout. To do this, we added a new ColdFusion tag called cfformgroup. You use this new tag to give formatting "hints" to the layout managers.

The layout managers use a number of rules to define the layout - such as defined widths, minimum widths of components, overall form size, available room left in the form, size of labels, and so forth. Because of these rules, the groups only provide hints, not hard-and-fast rules. The layout managers try to do what the group specifies, but if the fields don't fit, the managers lay out the fields in an alternative format, different from what you defined.

For instance, if you create a group using the type="horizontal" attribute, but you have 10 form elements in the group, odds are that 10 form fields side by side will appear wider then the form's space limit. In this case, the layout manager does what it can. Most likely, it will lay out three or four fields side by side, then output another three or four fields on the next line, and then output a new line with the last three fields.

This is different than when you lay out your form with the old HTML table methods, where each field lies in its own table cell. In this old scenario, the form renders off the side of the page to fit. When you find the layout managers rendering an unexpected output in ColdFusion MX 7, adjust the width of the form elements; usually reducing the width of the form fields a little can make the difference. If that doesn't work, increase the overall form width or remove the individual form element labels and use group labels instead. The following example demonstrates how you can use the cfformgroup tag to place the FirstName and LastName fields next to each other, with one shared label:


<cfformgroup type="horizontal"
   label="Enter Name:">
     <cfinput type="text"
        name="FirstName" value="">
<cfinput type="text" name="LastName"
   value="">
	</cfformgroup>

Better User Experience with Flash Forms
Layout managers were not the only reason we added the support for Flash forms. The desire for richer form controls and lack of cross-browser issues were contributing factors as well. To the cfformgroup tag , we also added some groups for Flash forms that did more than just lay out alignment - groups could now serve as layout containers as well. Examples of these containers are the tabnavigator, accordion, or panel layout containers.

In the following example, you can create tabs in your form using the tabnavigator container:


<cfform format="flash">
 <cfformgroup type="TabNavigator">
     <cfformgroup type="page"
       label="Tab 1">
         <!-- your form elements go 
           here --> 
     </cfformgroup>

<cfformgroup type="page" label=
  "Tab 2">
         <!-- your form elements go
            here --> 
     </cfformgroup>

<cfformgroup type="page" label=
  "Tab 3">
         <!-- your form elements go 
            here --> 
     </cfformgroup>
 </cfformgroup>
</cfform>

Perhaps the greatest reason for adding Flash forms support - a reason that was by far the most requested enhancement in ColdFusion since the merger of Allaire and Macromedia - was to replace the Java applets, specifically the cfgrid and cftree controls. For those of you who like the Java applets, don't worry, we kept them. But we added new Flash versions of the cfgrid and cftree controls (there are other new versions of the cfgrid and cftree tags as well: XML and object). These two controls are similar, but not identical, to the original versions. There are still some things that the Java applets do that the Flash controls cannot. Likewise, there are new things that the Flash cfgrid and cftree controls can do that the Java applets cannot. Use them; try them both. There is a time and place for both controls in your applications. For instance, the Java applets can handle a lot more data than the Flash controls. So if you need to output thousands of rows of data in a grid, use the Java applet controls.

Along with the new cfgrid and cftree controls, we added two new rich Flash controls to ColdFusion for dates and selecting dates. One of these controls is the cfcalendar tag you can use inside Flash, XML, and HTML forms (see Figure 1), just like the cfgrid and cftree controls. Another new control is the dateField type value for the cfinput tag. Use this control to create a text field with a pop-up calendar.

Note: You can only use the dateField type inside a Flash form.

Example:


<cfform format="flash">
	<cfinput type="dateField"
   name="startDate" label="Start
   Date:">
</cfform>

Of course, Flash forms may not be for everyone or for every form in your application. For instance, your application may not need the richness of Flash, or you may be unable to run Flash in your corporate environment. You may also need to use non-Flash controls, or need complete control of the whole form. This is where you would use the XML Forms feature.

If you want to take Flash forms to the next level and be able extend and customize the forms further than Flash forms allow, check out Macromedia Flex (www.macromedia.com/devnet/flex/).

Extending Forms with XML Forms
Since we introduced the cfform tag, there have been enhancement requests to improve it or complaints about the way we implemented it. With the introduction of the XML forms, these requests and complaints are no longer an issue. While Flash forms look and work great, XML forms give you the power to extend form functionality and layouts as you see fit, especially as you dig a little deeper and see what they have to offer.

We started to mull over the idea of XML forms years ago during the ColdFusion 6 development cycle. Conveniently, at the same time, the W3C was creating the XForms specification, which was finalized in the early days of ColdFusion MX 7 development. The XForms schema is designed as a way to describe a form in XML - including the model, elements, and validation - and with a way to extend the schema for custom implementations.

The idea behind the XML Forms in ColdFusion is similar to the Flash forms - to provide a way for you to define the form elements and layout manager hints. However, instead of having one predefined set of rules about the layout managers, you have endless possibilities.

The main benefit of XML Forms is the separation of presentation and logic. You can apply presentation "skins" to the forms in your application. As the developer, you define the fields and logic to manage the form, including default values, validation, and submitting to a database. Meanwhile, those in charge of the look and feel can pick the skin they want to apply and change it as much as they like. Six months from now, for instance, they could decide to change the look of their site completely. After making a quick change to the skin attribute or the XSL skin file, the form would have a new look and feel without the risk of accidentally changing the form logic.

If you want to write applications that change appearance for each user, XML forms give you an easy way to create a skin for each customer, reusing most of the same XSL code with only a few modifications - usually only to modify the CSS your form skin uses. In short, you can create a customized look for each application user.

The XML Forms use XSL files to skin your form. These style sheets give you complete control over how a browser displays your form. Besides, you were looking for an excuse to learn XML and XSL, right?

For instance, you could write a skin that generates the layout or the rendered HTML in browser-specific code. Doing this allows you to define the form functionality once and then use a variable, such as CGI.USER_AGENT, to switch between skins using browser-specific controls: a Firefox skin that uses CSS to render the layout, an Internet Explorer skin that uses tables, or a WAP skin to render the same form for those browsing your site from their phone.

I have found over the years that all my forms look the same. No matter what I do, my forms repeat the same HTML over and over again. With a custom XML skin, however, I can spend a little time creating my corporate skin, complete with the same table I always end up creating, a company logo, and any Section 508-compliant HTML requirements. By doing this, each form that my team or I create will have the same consistent look and feel. This brings "engineer art" to a whole new level!

To avoid confusion, many of the XForm examples available on the Internet require a browser plug-in. These are client-side implementations of XForms, where you must embed XForm XML elements inside of your XHTML document. With these examples the browser plug-in must then determine how to display the different elements in the browser. However, you still must use regular HTML to define the layout of form elements - one problem that ColdFusion MX 7 eliminates.

With ColdFusion, we implemented a server-side version that uses the XForms schema definitions for form elements, binding, and the model - with custom extensions instead of recreating the wheel and creating custom XML schema that defines form elements. However, instead of relying on a plug-in to render the form, ColdFusion MX 7 uses standard XSL scripts. If you wanted to use an XForms plug-in, you could use an XSL script to output plug-in friendly XForm XHTML and use one of the many XForm plug-ins to do the work on the client.

By letting the server-side scripts decide this, you can change the element definition on a skin-by-skin basis. For instance, perhaps you don't want to use a regular HTML textarea control. Instead, you would prefer to use a rich textarea control automatically, such as the Ektron text editor. Using a skin, you can automatically output the ActiveX code for the text editor every time a textarea form element is used.

With Flash forms we introduced new controls for the cfgrid and cftree tags; we have also done the same for XML Forms. In the XML forms, you can use the Java applet or Flash version of these controls, but you can also use the new "XML" format. This way, the XML describes the tree or grid with the tag attributes and generates the data in the XML form definition. In short, with this you can render controls as you like with your XSL scripts. For instance, you might want to output a DHTML grid instead, or perhaps you load an ActiveX control while still using the same simple cfgrid or cftree syntax in ColdFusion. As an example, I have used this XML format to turn the cftree into a DHTML menu.

Watch for additional articles in MXDJ about how to write your own skins. One easy way to learn about skins is to take one of the sample skins we shipped with ColdFusion MX 7. Save it as a new filename. At this point you now have a new skin. Edit the HTML that the skin outputs, the rules it includes (if you'd like to add support for some custom widget), or the CSS file that is associated with the skin. You have customized your first skin!

The Wait Is Over
Many of you at Macromedia MAX 2003 saw the early work we did on the cfform tag. Many of you wanted us to ship it then. Trust me, it was worth the wait to allow us to do the job right and polish up the form features. Thank you for your patience and feedback. I hope you find the new cfform tag to be a much more powerful and enjoyable experience to use.

© 2008 SYS-CON Media