Skip to main content
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with: Rachel Makrucki
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with: Rachel Makrucki

ColdFusion Custom Tags Should Have An End-Tag For Clarity

By
Published in Comments (3)

I've always been a big fan of custom tags in ColdFusion. But, in the last few years especially, I've ramped up my usage as part of my home-grown web application framework. In doing so, I've had to evolve the way I think about custom tags. Today, this evolution continues. Going forward, I'll start using self-closing custom tags as a rule (in a tag-based context) in order to provide clarity. Or, as James Moberg said in his CFSummit 2025 presentation, to "be explicit".

Aside: if you look in my BigSexyPoems /app/client folder, you'll see that my home-grown framework is just "custom tags all the way down". Since ColdFusion custom tags combine the encapsulation of ColdFusion components with the simple nestability of CFML templates, they really create an affordance for ideal collocation of files and locality of behaviors.

To illustrate the need for clarity / explicit self-closing custom tags, consider this snippet of CFML:

<cfmodule template="a.cfm">
<cfmodule template="b.cfm">
<cfmodule template="c.cfm">

<!--- Who do I belong to? --->
</cfmodule>

Since ColdFusion module tags can be:

  • Stand-alone
  • Paired
  • Self-closing

... it's not immediately clear which start-tag the </cfmodule> belongs to. Obviously, ColdFusion won't throw an error here — it has a heuristic that it uses in order to determine the association (it appears to use LIFO: Last In, First Out). But, I don't like that it's not clear to anyone who might read the code (including myself).

Consider this snippet of CFML:

<cfmodule template="a.cfm">
	<cfmodule template="b.cfm">

		<cfmodule template="c.cfm">

	</cfmodule>
</cfmodule>

Based on the indentation, you can see that the ColdFusion author intended a.cfm and b.cfm to be paired; and for c.cfm to be stand-alone. But, that's not how this code executes. Instead, ColdFusion executes it like this:

<cfmodule template="a.cfm">

<cfmodule template="b.cfm">
	<cfmodule template="c.cfm"></cfmodule>
</cfmodule>

ColdFusion creates a LIFO stack in which the most recent open-tags are automatically paired with the most recent close-tags. To remove any confusion, we'd have to change the c.cfm invocation to use the self-closing syntax:

<cfmodule template="a.cfm">
	<cfmodule template="b.cfm">

		<cfmodule template="c.cfm" /> <!--- Self-closing. --->

	</cfmodule>
</cfmodule>

This makes the code more explicit / less surprising. But, the side-effect of this change is that the c.cfm tag is now executed twice (as per the custom tag specification). We can counteract this side-effect by putting an exit tag / statement at the end of the c.cfm template:

<p> C.cfm </p>

<!--- Never execute the "end" tag-mode. --->
<cfexit />

Now, even if the c.cfm is invoked as a self-closing tag, only the "Start" execution mode will operate - the "End" mode will be omitted.

This is a really minor change to make in my ColdFusion coding methodology; but, I think it will actually make a big difference in terms of clarity. Shout-out to James for making me stop and think about this kind of foundational stuff.

This Does Not Apply To Using CFModule In Script

When invoking the CFModule tag in a script context (either in CFScript or within a ColdFusion component), there is no ambiguity about how custom tags will operate. In a script context, there is no third "self-closing" syntax. Modules either have a body, indicated by open/close braces; or, they are stand-alone:

<cfscript>

	cfmodule( template = "a.cfm" ) {
		cfmodule( template = "b.cfm" ) {

			cfmodule( template = "c.cfm" );

		}
	}

</cfscript>

In a script context, the braces remove all ambiguity. As such, the notion that "ColdFusion custom tags should have an end-tag for clarity" only applies to tags that are invoked in a tag-based context. So, really, this methodology change of mine only applies to tags that are intended to help render chunks of HTML.

Want to use code from this post? Check out the license.

Reader Comments

3 Comments

I created a custom tag that we use to replace CFFORM elements with HTML5, all within Bootstrap's grid system. Makes creating forms at least 80% faster. I may have to add this / option to make it even easier on my team. Thanks for the tip.

16,109 Comments

@Jack,

Form feels like a really natural place to consume customer tags. I've been thinking about it myself. In fact, I've had Flux open in a browser tab for several months now 😜 because it looks like there could be some really interesting stuff there to take inspiration from:

https://fluxui.dev/

It's written for PHP (which I know very little about). But it's written use "Blade templates", which seem to be very close parallels with ColdFusion custom tags. Like I said, I haven't actually done anything with it yet; but, you got me thinking about it once again.

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel
Managed hosting services provided by:
xByte Cloud Logo