Includes, Layouts, and Custom Tags
Understand the reuse mechanisms that shaped classic CFML applications and learn where each one belongs.
cfinclude
An included template executes in the caller's variable context. That makes includes convenient but tightly coupled.
<!--- index.cfm ---> <cfset variables.pageTitle = "Customer Portal"> <cfinclude template="includes/header.cfm"> <p>Page content</p> <cfinclude template="includes/footer.cfm">
The included file can read or overwrite variables from the caller. Document expected inputs and outputs or move complex behavior into a function, custom tag, or CFC.
Parameterized Includes
Because cfinclude has no formal arguments, older applications often set variables before including a template.
<cfset variables.panelTitle = "Open Tickets"> <cfset variables.panelQuery = openTickets> <cfinclude template="includes/ticket-panel.cfm">
This works, but the dependency is implicit. A custom tag provides an explicit attributes scope.
Custom Tags
<!--- Calling template --->
<cfmodule
template="/customtags/statusBadge.cfm"
status="#customer.status#">
<!--- customtags/statusBadge.cfm --->
<cfparam name="attributes.status" type="string" default="unknown">
<cfswitch expression="#attributes.status#">
<cfcase value="active"><span>Active</span></cfcase>
<cfcase value="suspended"><span>Suspended</span></cfcase>
<cfdefaultcase><span>Unknown</span></cfdefaultcase>
</cfswitch>
Returning a Value Through caller
<!--- customtags/calculateTotal.cfm ---> <cfparam name="attributes.quantity" type="numeric"> <cfparam name="attributes.unitPrice" type="numeric"> <cfset caller.calculatedTotal = attributes.quantity * attributes.unitPrice>
<!--- Calling template --->
<cfmodule
template="/customtags/calculateTotal.cfm"
quantity="3"
unitPrice="19.95">
<cfoutput>#DollarFormat(calculatedTotal)#</cfoutput>
Start and End Modes
Paired custom tags can process body content. The tag inspects thisTag.executionMode to distinguish its opening and closing execution.
<cfswitch expression="#thisTag.executionMode#">
<cfcase value="start">
<section class="legacy-panel">
</cfcase>
<cfcase value="end">
</section>
</cfcase>
</cfswitch>
When to Use Each Tool
| Tool | Best Fit | Risk |
|---|---|---|
cfinclude | Simple shared markup and small page fragments | Implicit shared variables and path coupling |
| Custom tag | Reusable view behavior or tag-like UI elements | Can mix business logic and presentation |
| User-defined function | Small transformation with clear inputs and output | Placement and shared scope can become unclear |
| CFC | Reusable services, gateways, and business logic | Incorrect method scoping can create concurrency bugs |
Legacy Layout Anti-Pattern
Some applications open HTML in a header include and close it in a footer or OnRequestEnd.cfm. A thrown exception or early cfabort can leave incomplete output. When modernizing, prefer templates whose structure is visible and balanced.