The Scopes lesson introduced form as one of CFML's built-in scopes. This lesson covers forms in practice: how a plain HTML form's fields actually arrive in that scope, a real gotcha with controls that don't always submit, and cfform, ColdFusion's own tag for building a form with built-in client-side validation.
Learning Objectives
After completing this lesson, you'll be able to:
- Build an HTML form whose fields land in the form scope on the action page.
- Recognize which controls silently omit themselves from form scope when nothing is selected.
- Use cfform and its CFML control tags for a form with built-in client-side validation.
How a Form Submission Reaches Your Code
Browser Renders <form>
User Submits
action Page Runs
Fields Available as form.fieldName
A Basic Form
<form action="process-signup.cfm" method="post">
<input type="text" name="firstName">
<input type="email" name="email">
<button type="submit">Sign Up</button>
</form><cfoutput>
Welcome, #form.firstName#! We'll email you at #form.email#.
</cfoutput>The Real Gotcha: Checkboxes, Radios, and Listboxes
Checkboxes, radio buttons, and list boxes do not pass data to the action page unless something is actually selected. An unchecked checkbox doesn't submit as false, it doesn't submit at all, meaning form.newsletter simply won't exist if the box was left unchecked.
<cfparam name="form.newsletter" default="false">
<cfif form.newsletter EQ "true">
<cfset subscribeToNewsletter(form.email)>
</cfif>cfparam sets a default only if the variable doesn't already exist, exactly the case an unchecked checkbox produces. structKeyExists(form, "newsletter") works just as well as an explicit check.
cfform: ColdFusion's Own Form-Building Tag
cfform builds a form using CFML's own control tags, cfinput, cfselect, cftextarea, cfslider, cfgrid, cftree, which support all the same attributes as their HTML counterparts plus additional ColdFusion features, most notably built-in client-side validation (covered in depth in the next lesson).
cfform's Core Attributes
| Attribute | Meaning |
|---|---|
| name | The form's name (auto-generated if omitted) |
| action | Where the form submits to |
| method | post (default) or get |
| format | html, the only format still supported — see the note below |
| preserveData | Whether submitted values repopulate the form if it's reloaded (default no) |
| onSubmit / onReset / onLoad | JavaScript hooks for the form's lifecycle |
| scriptSrc | Custom directory for cfform's own JavaScript library, default /CFIDE/scripts |
A Real Example: A Login Form With Built-in Required Validation
<cfform action="process-login.cfm" method="post">
<cfinput type="text" name="username" required="yes" message="Username is required.">
<cfinput type="password" name="password" required="yes" message="Password is required.">
<cfinput type="submit" name="submitBtn" value="Log In">
</cfform>cfinput's required and message attributes generate client-side validation automatically, no separate JavaScript needed for this simple case, the next lesson covers validation in depth, including why server-side validation is still necessary regardless.
A Real Engine/Version Difference: cfform's Flash-Forms History
cfform historically also supported generating Flash-based forms (format="flash"), with attributes like height, width, skin, timeout, wmode, accessible, codeBase, and archive controlling the embedded Flash player. Adobe's 2025 ColdFusion release removed Flash and XML form support entirely, only html remains. Lucee never supported Flash or XML forms at all, and as of Lucee 7 the form tag itself requires a separate "Form Tags for Jakarta EE" extension to be installed.
Common Beginner Mistakes
Assuming an unchecked checkbox submits as false
It doesn't submit at all, form.fieldName won't exist. Default it with cfparam, or check structKeyExists(form, "fieldName") before reading it.
Using cfform attributes like height, width, or skin, expecting Flash-form behavior
Those were tied to Flash-based forms, removed entirely in Adobe's 2025 release. They no longer do anything.
Assuming client-side validation from cfinput's required attribute is enough on its own
Client-side validation only stops a well-behaved browser, it does nothing against a request sent directly to the action page. Server-side validation, covered in the next lesson, is still necessary.
Best Practices
- Default checkbox, radio, and listbox fields with cfparam (or check structKeyExists) before reading them, they may simply not be present.
- Reach for cfform's controls when built-in client-side validation genuinely saves real work, plain HTML forms remain perfectly valid for everything else.
- Don't rely on legacy cfform attributes tied to the removed Flash-forms functionality.
- Treat client-side validation as a user-experience convenience, not a security or data-integrity boundary.
Interview Questions
Why might form.newsletter not exist even though a checkbox named newsletter was on the form?
Checkboxes, radio buttons, and list boxes only pass data to the action page when something is actually selected, an unchecked checkbox doesn't submit at all.
What does cfform offer beyond a plain HTML form?
CFML's own control tags (cfinput, cfselect, cftextarea, cfslider, cfgrid, cftree), which support all the same attributes as their HTML equivalents plus ColdFusion-specific features, most notably built-in client-side validation.
What happened to cfform's Flash-forms support?
Adobe removed Flash and XML form support entirely in the 2025 release, only html format remains. Lucee never supported them, and Lucee 7 requires a separate extension for the form tag at all.
Summary
In this lesson, you built an HTML form whose fields land in the form scope, handled the real gotcha where unselected checkboxes, radios, and listboxes don't submit at all, and used cfform and its CFML control tags for a form with built-in client-side validation.
What's Next?
The next lesson covers form validation in depth: client-side validation with cfinput, and why server-side validation is still required regardless of what the browser already checked.