Glossary

What Is a ColdFusion Custom Tag?

Definition

A ColdFusion custom tag is a reusable CFML file that you invoke like a tag to encapsulate logic or presentation. In simple terms, it’s a .cfm template that behaves like a function with attributes, can render output, and can optionally wrap body content. You call it using a tag-style Syntax (for example, <cf_myTag …> or via cfmodule), pass attributes to it, and the tag executes its code and optionally returns output or data to the caller. It’s a core way to build a custom tag library in ColdFusion/CFML for consistent, modular development.


How It Works

The basic idea

  • You create a CFML file (for example, showTable.cfm).
  • You call it like a tag: .
  • The custom tag receives your inputs through the special ATTRIBUTES scope and can send data back via the CALLER scope or by writing output.

Where ColdFusion finds Custom tags

ColdFusion looks for the tag file in:

  • The same directory as the calling page
  • Any directories configured in this.customTagPaths in Application.cfc
  • The server’s Custom Tag Paths (ColdFusion Administrator)
  • A directory imported via cfimport taglib

Ways to invoke a custom tag

  • Tag-style:
  • Module-style:
  • Namespaced (via cfimport): <ui:myTag …> after cfimport taglib=”/path/to/tags” prefix=”ui”
See also  What Is ColdFusion Admin API?

Anatomy of a Custom Tag

Inside a custom tag template (the .cfm file), you use a few special scopes and conventions:

  • ATTRIBUTES: A struct of all attributes passed to the tag. Example: attributes.title
  • VARIABLES: The tag’s private scope for local variables; safe from the caller’s variables.
  • CALLER: The calling page’s scope; use it to return values (carefully).
  • THIS.TAG (or ThisTag): A struct with runtime info about the tag, such as:
    • ThisTag.ExecutionMode: “start” or “end”
    • ThisTag.HasEndTag: true/false
    • ThisTag.GeneratedContent: content between start and end tags

Common patterns:

  • Validate inputs with cfparam on attributes
  • Render or capture output
  • Optionally put results into caller scope

Passing Attributes and Default values

  • Pass attributes just like any CFML tag:
  • Read attributes in the tag file using the ATTRIBUTES scope.
  • Provide defaults and type checks using cfparam:

You can also pass dynamic sets of attributes using attributeCollection with cfmodule or namespaced tags:


Execution Modes and Body Content

Custom tags can be used with or without an end tag:

  • Self-closing:
  • Paired: … inner HTML or CFML …

When you use a start and end tag, ColdFusion runs the tag twice:

  • Start run (ThisTag.ExecutionMode = “start”)
  • End run (ThisTag.ExecutionMode = “end”), where ThisTag.GeneratedContent contains the inner content

This makes it easy to wrap markup around body content.


Syntax and Examples

Example 1: A simple outputting tag

File: /customtags/formatDate.cfm

  • <cfset variables.out = dateFormat(attributes.date, attributes.format)>
  • #variables.out#

Usage:

Example 2: A wrapping tag that uses GeneratedContent

File: /customtags/panel.cfm

  • <cfif ThisTag.ExecutionMode EQ “start”>
  • <cfelseif ThisTag.ExecutionMode EQ “end”>
    • #encodeForHtml(attributes.title)#

      #ThisTag.GeneratedContent#

Usage:


  • #dateFormat(now(), “mmm d, yyyy”)#
    • Order #1
    • Order #2

Example 3: Returning values to the caller

File: /customtags/makeSlug.cfm

  • <cfset variables.slug = rereplace(lcase(attributes.text), “[^a-z0-9]+”, “-“, “all”)>
  • <cfset variables.slug = rereplace(variables.slug, “^-|-$”, “”, “all”)>

Usage:

  • #slug#

Real-World Use Case: Reusable Pagination Widget

Imagine multiple pages listing records. You want a consistent pagination bar.

Tag file: /customtags/pager.cfm

  • <cfset variables.totalPages = ceiling(attributes.totalRows / attributes.pageSize)>

Usage:

Benefit: You centralize logic and UI for pagination, ensuring consistency and easier updates.

See also  What Is ColdFusion CFML?

Use Cases and Patterns

  • UI components and wrappers: panels, tabs, alerts, grids, cards
  • Content filters/formatters: date formatting, slug generation, currency display
  • Reusable data widgets: pagers, breadcrumbs, tag clouds
  • Layout composition: wrappers that capture body content and apply a theme or template
  • Cross-cutting concerns: standardized error messaging, auditing output, conditional rendering
  • Namespaced libraries: via cfimport to avoid name collisions and improve readability

Pros and cons

Pros:

  • Encapsulation of presentation and logic
  • Clean, declarative usage in templates
  • Easy attribute passing and body content handling
  • Simple sharing via directories or cfimport as a tag library

Cons:

  • Less explicit than calling functions for pure logic
  • Overuse can lead to deeply nested templates
  • Can write directly to output buffer unless you control it
  • For pure Business logic, CFCs/UDFs may be clearer and more testable

Best practices

  • Validate inputs with cfparam and provide sensible defaults.
  • Use VARIABLES scope for internals; only touch CALLER when you must return values.
  • Prefer writing HTML output deliberately; if needed, capture content with cfsavecontent and return a string to the caller.
  • Support both tag and cfmodule invocation where appropriate.
  • Consider namespacing with cfimport (prefix=”ui”) to avoid conflicts and to group related tags.
  • Document attributes (required, optional, types) and side effects (e.g., variables set in caller).
  • Keep tags focused; if you find complex Business logic, move it into CFC services and call them from your tag.
  • Handle errors predictably with cftry/cfcatch and cfthrow; fail fast on invalid attributes.
  • For Deployment, centralize tag directories and configure this.customTagPaths in Application.cfc.

Key Points and Comparisons

  • Custom tag vs. UDF (User-Defined Function):

    • Use a custom tag for declarative UI or when wrapping body content is helpful.
    • Use a UDF for pure computation and returning values without output concerns.
  • Custom tag vs. CFC method:

    • CFCs are better for domain logic, services, and testing.
    • Custom tags shine in templating and reusable view components.
  • cf_tag vs. cfmodule:

    • cf_tag is concise and relies on tag lookup rules.
    • cfmodule is explicit (template path) and works well when you want to bypass lookup or pass attributeCollection.
  • Namespacing with cfimport:

    • Use syntax for clarity and to organize tag libraries.
See also  What Is CFLOOP in ColdFusion?

Troubleshooting and Common pitfalls

  • “Could not find the ColdFusion custom tag”:

    • Check file name and location; verify Application.cfc this.customTagPaths or server Custom Tag Paths.
    • Try cfmodule with an absolute/relative template path to confirm availability.
  • Attributes not found or wrong type:

    • Add cfparam for each attribute, defining type, default, and required properties.
  • Output appearing in the wrong place:

    • Control output carefully; consider cfsavecontent or cfsetting enablecfoutputonly=”true” in complex pages.
  • Body content not captured:

    • Ensure you use paired tags and check ThisTag.ExecutionMode on “end”; use ThisTag.GeneratedContent.
  • Scope collisions:

    • Always use VARIABLES when creating internal variables; set CALLER variables intentionally and with clear names.

FAQ

What is the difference between a custom tag and cfinclude?

cfinclude simply inserts and executes another CFML file inline, without attribute handling or special scopes. A custom tag adds structured attribute passing, body content wrapping, and tag lifecycle Features (start/end modes), making it better for reusable components.

Can custom tags return values like functions?

Indirectly, yes. A custom tag can place values into the CALLER scope or return rendered output. For function-like behavior (returning a value), consider populating CALLER.someVar or capturing output with cfsavecontent and assigning it to a variable.

How do I organize and import a custom tag library?

Place related .cfm tag files in a directory (e.g., /tags/ui). Then use cfimport taglib=”/tags/ui” prefix=”ui” and call them as , , etc. You can also set this.customTagPaths in Application.cfc for global availability.

Are custom tags still recommended if I use CFCs?

Yes, for presentation and templating concerns. Use CFCs for business logic and services; call them from custom tags when rendering UI. This separation keeps views clean and logic testable.

Can custom tags be nested or communicate with each other?

Yes. You can build nested tags (e.g., with ) and share data using ThisTag, GeneratedContent, GetBaseTagData(), and, for advanced scenarios, cfassociate. This supports sophisticated component composition.

About the author

Aaron Longnion

Aaron Longnion

Hey there! I'm Aaron Longnion — an Internet technologist, web software engineer, and ColdFusion expert with more than 24 years of experience. Over the years, I've had the privilege of working with some of the most exciting and fast-growing companies out there, including lynda.com, HomeAway, landsofamerica.com (CoStar Group), and Adobe.com.

I'm a full-stack developer at heart, but what really drives me is designing and building internet architectures that are highly scalable, cost-effective, and fault-tolerant — solutions built to handle rapid growth and stay ahead of the curve.