Form Validation
- To understand the basics of the <cfform> tag.
- To work with ColdFusion's auto-generated client-side form validation using <cfform>.
- To work with ColdFusion's auto-generated server-side form validation using <cfform>.
- To work with ColdFusion's auto-generated server-side form validation without <cfform>.
- To create input masks.
- To write your own server-side form validation code.
<cfform> Basics
The <cfform> tag is used to generate HTML forms. ColdFusion form controls, such as <cfinput>, <cfselect>, and <cftextarea> are used inside of <cfform> to create HTML entry fields. The table below shows <cfform>'s attributes for HTML forms.
| Attribute | Description |
|---|---|
| name | form name |
| action | form action |
| method | form method: "post" or "get" |
| format | "html" for HTML forms |
Code Sample: FormValidation/Demos/AddEntry-cfform.cfm
<html> <head> <title>Running Log</title> </head> <body> <cfform name="RunningForm" method="post" action="AddEntry-cfform.cfm" format="html"> <table> <tr> <td>Date:</td> <td><cfinput type="text" name="date" size="20"></td> </tr> <tr> <td>Distance:</td> <td><cfinput type="text" name="distance" size="20"></td> </tr> <tr> <td>Time:</td> <td><cfinput type="text" name="time" size="20"></td> </tr> <tr> <td>Comments:</td> <td><cftextarea rows="3" cols="40" name="comments"></cftextarea></td> </tr> <tr> <td colspan="2" align="right"> <cfinput type="submit" name="Add Entry" value="Add Entry"> </td> </tr> </table> </cfform> </body> </html>
The generated HTML form code is shown below:
<form name="RunningForm" action="AddEntry-cfform.cfm" method="post" onsubmit="return _CF_checkRunningForm(this)"> <table> <tr> <td>Date:</td> <td><input name="date" id="date" type="text" size="20"/></td> </tr> <tr> <td>Distance:</td> <td><input name="distance" id="distance" type="text" size="20"/></td> </tr> <tr> <td>Time:</td> <td><input name="time" id="time" type="text" size="20"/></td> </tr> <tr> <td>Comments:</td> <td><textarea name="comments" rows="3" cols="40" ></textarea></td> </tr> <tr> <td colspan="2" align="right"> <input name="Add Entry" id="Add Entry" type="submit"/> </td> </tr> </table> </form>
As you can see, it is a basic HTML form with nothing too special about it. However, ColdFusion form tags can do some pretty neat things with the right attributes. In this lesson, we'll learn how to use them to validate forms.
Auto-generated Form Validation
Form Validation with <cfform>
Using the <cfform> in place of the <form> tag allows you to take advantage of ColdFusion's auto-generated validation code, which can be run client-side with JavaScript before the form actually submits or server-side after the form submits.
For input fields that you wish to validate in this way, use <cfinput> instead of <input>. To require that a field be filled in, set required="yes" in the <cfinput> tag.
In addition to checking whether or not a field is filled in, you can check that fields conform to specific types of patterns by assigning the appropriate value to the validate attribute of <cfinput> or <cftextarea>.
| Suffix | Description |
|---|---|
| numeric | Numeric. The following special characters are allowed and kept: $ ¤ ¥ £ +. |
| integer | Integer. The following special characters are allowed but stripped: $ ¤ ¥ £ +. |
| float | Float. The following special characters are allowed but stripped: $ ¤ ¥ £ +. |
| range | Value must be within range specified by the value attribute in the format "min=minvalue max=maxvalue". No custom error message is allowed. |
| date | Date/time that ColdFusion can understand. ColdFusion converts the value into ODBC date format (without the time). |
| time | Date/time that ColdFusion can understand. ColdFusion converts the value into ODBC time format (without the date). |
| usdate | U.S. date. Allowed formats: m/d/y, m-d-y , or m.d.y |
| eurodate | European date. Allowed formats: d/m/y, d-m-y, or d.m.y |
| creditcard | Number between 13-16 digits that conforms to the mod10 algorithm. Spaces and dashes are stripped. |
| SSN | Nine-digit Social Security number separated by dashes or spaces. |
| telephone | U.S. telephone number with or without area codes and extensions. |
| zipcode | 5 or 9 digit U.S. ZIP code. |
| Valid email address. | |
| URL | Valid URL. |
| boolean | Boolean. (Yes, No, True, False, 1, 0) |
| UUID | Universally unique identifier (UUID) that follows the ColdFusion format, xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx, where x is a hexadecimal number. |
| GUID | Unique identifier that follows the Microsoft/DCE format, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where x is a hexadecimal number. |
| noblanks | Value must contain at least one non-whitespace character. Field must also be specified as required using required. |
| maxlength | Value cannot contain more characters than specified by the maxlength attribute. No custom error message is allowed. |
| regex | Value must match regular expression defined in the pattern attributed. |
| SubmitOnce | Used in submit buttons to prevent a user from submitting a form multiple times by mistake. |
The validateat Attribute
The validateat attribute specifies where the form validation should take place. Options are onsubmit (default), onblur, and onserver. The first two options use client-side form validation. The last one uses server-side validation.
Below is an example of how to use <cfform> to validate the running log entry form using client-side form validation.
Code Sample: FormValidation/Demos/AddEntry-onsubmit.cfm
---- Code Omitted ----<cfform name="RunningForm" method="post" action="#CGI.SCRIPT_NAME#" format="html"> <table> <tr> <td>Date:</td> <td><cfinput type="text" name="date" size="20" required="yes" validate="date" validateat="onsubmit" message="You must enter a valid date."></td> </tr> <tr> <td>Distance:</td> <td><cfinput type="text" name="distance" size="20" required="yes" validate="float" validateat="onsubmit" message="You must enter a valid number for the distance."></td> </tr> <tr> <td>Time:</td> <td><cfinput type="text" name="time" size="20" required="yes" validate="regex" pattern="^\d{1,3}:\d{0,2}$" validateat="onsubmit" message="You must enter a valid time in the format mm:ss."></td> </tr> <tr> <td>Comments:</td> <td><cftextarea rows="3" cols="40" name="comments" required="yes" validate="maxlength" maxlength="50" validateat="onsubmit" message="The comment must be between 1 and 50 characters."></cftextarea></td> </tr> <tr> <td colspan="2" align="right"> <cfinput type="submit" name="AddEntry" value="Add Entry"> </td> </tr> </table> </cfform> </body> </html>
The form checks for the following:
- The date is filled in and is a valid date.
- The distance is filled in and is a valid float.
- The time is filled in and corresponds to a specified regular expression. (Note this is a time in minutes and seconds (mm:ss), not a time of day, so we don't check to see if it is a valid time.)
- The comments field is filled in.
If the form is submitted with errors, the following alert will pop up:
![]()
Below is an example of how to use <cfform> to validate the running log entry form using server-side form validation. The only change is the value of the validateat attribute.
Code Sample: FormValidation/Demos/AddEntry-onserver.cfm
---- Code Omitted ----<cfform name="RunningForm" method="post" action="#CGI.SCRIPT_NAME#" format="html"> <table> <tr> <td>Date:</td> <td><cfinput type="text" name="date" size="20" required="yes" validate="date" validateat="onserver" message="You must enter a valid date."></td> </tr> <tr> <td>Distance:</td> <td><cfinput type="text" name="distance" size="20" required="yes" validate="float" validateat="onserver" message="You must enter a valid number for the distance."></td> </tr> <tr> <td>Time:</td> <td><cfinput type="text" name="time" size="20" required="yes" validate="regex" pattern="^\d{1,3}:\d{0,2}$" validateat="onserver" message="You must enter a valid time in the format mm:ss."></td> </tr> <tr> <td>Comments:</td> <td><cftextarea rows="3" cols="40" name="comments" required="yes" validate="maxlength" maxlength="50" validateat="onserver" message="The comment must be between 1 and 50 characters."></cftextarea></td> </tr> <tr> <td colspan="2" align="right"> <cfinput type="submit" name="AddEntry" value="Add Entry"> </td> </tr> </table> </cfform> </body> </html>
The form makes the same checks as we saw with the client-side validation, but is validated server-side.
If the form is submitted with errors, the page will display as follows:
![]()
Although it is possible to customize this error template, you do not have as much control over the look and feel of the page as you would if you wrote the form validation code yourself.
Behind the Curtain of Server-Side Validation
What's happening behind the curtain here? The <cfform> tag and its friends (<cfinput>, <cfselect>, etc.) are performing a little magic by auto-generating standard HTML form controls. For each piece of validation, hidden fields are added that ColdFusion later uses to know what type of validation to perform. The developer is also able to add these hidden fields directly, which is useful when not using <cfform>. In older versions of ColdFusion (MX 6 and earlier), this was the only way to get ColdFusion to auto-generate server-side validation. This is discussed in the next section.
Server-Side Validation without <cfform>
Through the use of hidden <input> fields in a form, you can get ColdFusion to do some basic server-side form validation for you. The name of the hidden fields must be the same name as the field to be validated followed by an underscore (_) followed by a suffix, which indicates the type of validation. Starting with ColdFusion MX 7, suffixes begin with "cfform"; however, for the validation types that were supported in older versions, the old suffix will still work.
ColdFusion returns the value of the hidden field as the error message.
The table below describes the hidden fields suffixes.
| Suffix | Old Suffix | Description |
|---|---|---|
| _cfformrequired | _required | Field must be filled out or selected. If this is not set, then the field will not be required, even if other validation rules are set. |
| _cfformnumeric | n/a | Numeric. The following special characters are allowed: $ ¤ ¥ £ + and kept. |
| _cfforminteger | _integer | Integer. The following special characters are allowed: $ ¤ ¥ £ + but stripped. |
| _cfformfloat | _float | Float. The following special characters are allowed: $ ¤ ¥ £ + but stripped. |
| _cfformrange | _range | Value must be within range specified by the value attribute in the format "min=minvalue max=maxvalue". No custom error message is allowed. |
| _cfformdate | _date | Date/time that ColdFusion can understand. ColdFusion converts the value into ODBC date format (without the time). |
| _cfformtime | _time | Date/time that ColdFusion can understand. ColdFusion converts the value into ODBC time format (without the date). |
| _cfformusdate | n/a | U.S. date. Allowed formats: m/d/y, m-d-y , or m.d.y |
| _cfformeurodate | _eurodate | European date. Allowed formats: d/m/y, d-m-y, or d.m.y |
| _cfformcreditcard | n/a | Number between 13-16 digits that conforms to the mod10 algorithm. Spaces and dashes are stripped. |
| _cfformSSN | n/a | Nine-digit Social Security number separated by dashes or spaces. |
| _cfformtelephone | n/a | U.S. telephone number with or without area codes and extensions. |
| _cfformzipcode | n/a | 5 or 9 digit U.S. ZIP code. |
| _cfformemail | n/a | Valid email address. |
| _cfformURL | n/a | Valid URL. |
| _cfformboolean | n/a | Boolean. (Yes, No, True, False, 1, 0) |
| _cfformUUID | n/a | Universally unique identifier (UUID) that follows the ColdFusion format, xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx, where x is a hexadecimal number. |
| _cfformGUID | n/a | Unique identifier that follows the Microsoft/DCE format, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where x is a hexadecimal number. |
| _cfformnoblanks | n/a | Value must contain at least one non-whitespace character. Field must also be specified as required using _cfformrequired. |
| _cfformmaxlength | n/a | Value cannot contain more characters than specified by the value attribute. No custom error message is allowed. |
| _cfformregex | n/a | Value must match regular expression. |
<input type="text" name="age"> <input type="hidden" name="age_cfforminteger" value="Age must be a valid integer.">
Below is an example of how to use hidden fields to validate the running log entry form.
Code Sample: FormValidation/Demos/AddEntry-hidden.cfm
---- Code Omitted ----<form method="post" action="#CGI.SCRIPT_NAME#"> </cfoutput> <input type="hidden" name="submitted" value="true"> <table> <tr> <td>Date:</td> <td><input type="text" name="date" size="20"></td> <input type="hidden" name="date_cfformrequired" value="You must enter a date."> <input type="hidden" name="date_cfformdate" value="The date you entered is not a valid date."> </tr> <tr> <td>Distance:</td> <td><input type="text" name="distance" size="20"></td> <input type="hidden" name="distance_cfformrequired" value="You must enter a distance."> <input type="hidden" name="distance_cfformfloat" value="The distance you entered is not a valid number."> </tr> <tr> <td>Time:</td> <td><input type="text" name="time" size="20"></td> <input type="hidden" name="time_cfformrequired" value="You must enter a time."> <input type="hidden" name="time_cfformregex" value="^\d{1,3}:\d{0,2}$"> </tr> <tr> <td>Comments:</td> <td><input type="text" name="comments" size="50"></td> <input type="hidden" name="comments_cfformrequired" value="You must enter a comment."> <input type="hidden" name="comments_cfformmaxlength" value="50"> </tr> <tr> <td colspan="2" align="right"> <input type="submit" name="Add Entry"> </td> </tr> </table> </form> </body> </html>
The form makes the same checks as before, but using this method, it is possible to have different error messages based on the type of error.
If the form is submitted without filling any of the fields in, a page that looks like the screenshot below will appear:
![]()
If the form is completely filled in, but the fields are invalid, the resulting page will look like this:
![]()
Although it is possible to customize this error template, you do not have as much control over the look and feel of the page as you would if you wrote the form validation code yourself.
Masking Input Values
The <cfinput> tag has a mask attribute that controls the format the user enters into a text field. The syntax is as follows:
<cfinput type="text" name="phone" mask="(999) 999-9999">
The table below shows the mask characters for HTML fields:
| Character | Description |
|---|---|
| A | A-Z (case-insensitive) |
| X | A-Z (case-insensitive) or 0-9 |
| 9 | 0-9 |
| ? | Any character |
| Other Characters | Inserts literal character |
The code sample below shows some samples of masking:
Code Sample: FormValidation/Demos/Masks.cfm
<html> <head> <title>Masks</title> </head> <body> <cfform method="post" action="#CGI.SCRIPT_NAME#" format="html"> Phone: <cfinput type="text" name="phone" mask="(999) 999-9999"><br/> SSN: <cfinput type="text" name="ssn" mask="999-99-9999"><br/> Course ID: <cfinput type="text" name="ssn" mask="AAA99X"><br/> <cfinput type="submit" name="Submit" value="Submit"> </cfform> </body> </html>
Open the page in your browser and enter fields. You will notice that the format of your entry is controlled and that some characters are automatically inserted.
Custom Server-Side Form Validation
Writing your own custom server-side form validation gives you a lot more flexibility and control. Take a look at the following code.
Code Sample: FormValidation/Demos/AddEntry-custom.cfm
<cfparam name="FORM.date" default="">
<cfparam name="FORM.distance" default="">
<cfparam name="FORM.time" default="">
<cfparam name="FORM.comments" default="">
<html>
<head>
<title>Running Log</title>
<style>
.errors {color:red; font-weight:bold}
.cool {color:black}
</style>
</head>
<body>
<cfparam name="errors" default="">
<cfif isDefined("FORM.submitted")>
<cfif NOT isDate(FORM.date)>
<cfset errors = errors & "<li>The date is invalid.</li>">
<cfset dateclass="errors">
</cfif>
<cfif NOT ListLen(FORM.distance," ") EQ 2>
<cfset errors = errors & "<li>The distance must be in the format <i>num units</i>.</li>">
<cfset distanceclass="errors">
<cfelse>
<cfset intDistance = ListGetAt(FORM.distance,1," ")>
<cfset units = ListGetAt(FORM.distance,2," ")>
<cfif NOT isNumeric(intDistance)>
<cfset errors = errors & "<li>The distance must be in the format <i>num units</i>.</li>">
<cfset distanceclass="errors">
</cfif>
</cfif>
<cfif Len(errors) EQ 0>
<cfset RunningLogPath = ExpandPath("Logs/RunningLog.txt")>
<cfset Tab = chr(9)>
<cfset outputstring = "#FORM.date##Tab##FORM.distance##Tab##FORM.time##Tab##FORM.comments#">
<cffile action="append" file="#RunningLogPath#" output="#outputstring#" addnewline="yes">
<h1 align="center">Entry added</h1>
<a href="RunningLog.cfm">Running Log</a>
<!---Clean up variables--->
<cfset FORM.date="">
<cfset FORM.distance="">
<cfset FORM.time="">
<cfset FORM.comments="">
</cfif>
</cfif>
<h1 align="center">Add Entry</h1>
<cfoutput>
<form method="post" action="#CGI.SCRIPT_NAME#">
<input type="hidden" name="submitted" value="true">
<table>
<cfparam name="dateclass" default="cool">
<cfparam name="distanceclass" default="cool">
<cfparam name="timeclass" default="cool">
<cfparam name="commentsclass" default="cool">
<cfif Len(errors) GT 0><!---checking for errors--->
<tr><td colspan="2" style="margin-left:20px">
<h3>Errors</h3>
<ul class="errors">
#errors#
</ul>
</td></tr>
</cfif>
<tr>
<td>Date:</td>
<td><input type="text" name="date" size="20" value="#FORM.date#" class="#dateclass#"></td>
</tr>
<tr>
<td>Distance:</td>
<td><input type="text" name="distance" size="20" value="#FORM.distance#" class="#distanceclass#"></td>
</tr>
<tr>
<td>Time:</td>
<td><input type="text" name="time" size="20" value="#FORM.time#" class="#timeclass#"></td>
</tr>
<tr>
<td>Comments:</td>
<td><input type="text" name="comments" size="50" value="#FORM.comments#" class="#commentsclass#"></td>
</tr> ---- Code Omitted ----
This form only validates the first two fields.
- The date must be a valid date.
- The distance must be in the format "num units" (e.g, 9 miles).
If the form is submitted without filling any of the fields in, a page that looks like the screenshot below will appear:
![]()
The validation is handled as follows:
- An errors variable is created using <cfparam> containing an empty string.
- When the form is submitted, the fields needing validation are checked one by one. If an error is found, text is appended to the errors variable in the form of an HTML list item and a variable holding the class for that field is set to "errors". That variable is used inside the <input> fields to determine how the field should be displayed.
- After each field has been checked, the length of the string held in errors is checked. If it is a zero-length string, that means there are no errors and the entry is added to the log.
- Within the HTML form itself, the length of errors is checked again. If it is not a zero-length string, then the error message is output.
IsValid()
The IsValid() function is useful for checking whether a variable or value is of a certain data type or meets pattern, size or length constraints. There are three possible signatures for IsValid().
IsValid(type, value)
isValid("range", value, min, max)
isValid("regex", value, pattern)Possible types are the same as those shown in the "<cfinput> and <cftextarea> Validate Values" table at the beginning of this lesson. In addition, the type can be any of the following:
| Suffix | Description |
|---|---|
| any | Same as IsSimpleValue(). |
| array | Same as IsArray(). |
| binary | Same as IsBinary(). |
| query | Same as IsQuery(). |
| struct | Same as IsStruct(). |
Form Validation Conclusion
Although ColdFusion's auto-generated form validation makes it quick and easy to validate forms, it makes it very difficult to provide a customized user interface for handling errors.
