Skip to main content
Ben Nadel at CFUNITED 2010 (Landsdown, VA) with: Ken Auenson
Ben Nadel at CFUNITED 2010 (Landsdown, VA) with: Ken Auenson

ColdFusion Custom Tags Can Use Dashes In Tag Names

By
Published in Comments (1)

Yesterday, I was looking at the Laravel Flux UI framework; and was impressed with how clearly they've codified their approach to custom tag organization. I wanted to borrow their thinking to do some exploration on the ColdFusion side. In Flux, they use the dot (.) to namespace their tags. This doesn't work in ColdFusion; but, I was pleasantly surprised to see that dashes (-) can be used in custom tag identifiers.

In the Flux UI framework, they use two conventions for grouping custom tags. If a tag can meaningfully stand on its own - such as the Button tag - they provide a parent tag with a .group suffix. Example:

<flux:button.group>
	<flux:button />
</flux:button.group>

However, if a tag doesn't make sense on its own - such as with the Breadcrumb item tag - they use a .item suffix on each of the children. Example:

<flux:breadcrumbs>
	<flux:breadcrumbs.item />
</flux:breadcrumbs>

On the ColdFusion side, we can't use . in custom tag identifiers; but, after some trial-and-error, I discovered that we can use dashes. It doesn't read quite at nicely as the dots; but, it can be used to drive the same kind of organizational philosophy.

Note: in ColdFusion, the dot (.) can be used to namespace directories for custom tags, much like it can be used to namespace directories for ColdFusion components.

To explore, let's setup a demo ColdFusion application that defines a per-application setting for custom tag paths. The following code tells the ColdFusion server to look in the local ./tags directory for custom tags before looking in the server's global custom tags directory.

component {

	this.name = "ModuleNameTest";
	this.applicationTimeout = createTimeSpan( 0, 1, 0, 0 );
	this.sessionManagement = false;
	this.setClientCookies = false;

	this.webroot = getDirectoryFromPath( getCurrentTemplatePath() );

	// ColdFusion will look in this directories for custom tags.
	// --
	// Note: Adobe ColdFusion will recursively search through the custom tag paths looking
	// for matching tag names. Lucee CFML will NOT search recursively. As such, this demo
	// doesn't work identically in both CFML runtimes.
	this.customTagPaths = arrayToList([
		"#this.webroot#tags"
	]);

}

Pursuant to the Flux UI approach, let create two ColdFusion custom tags that have a grouping relationship:

  • Thing-Group.cfm
  • Thing.cfm

Behind the scenes, this does nothing but mimic HTML's ul/li parent-child relationship; but, note that the grouping custom tag has a dash in the name.

Now, let's try to invoke these ColdFusion custom tags using various mechanics:

<cf_thing-group style="cf_">
	<cf_thing>Anna</cf_thing>
	<cf_thing>Anna</cf_thing>
	<cf_thing>Bo-banna</cf_thing>
	<cf_thing>Banana-fanna fo-fanna</cf_thing>
	<cf_thing>Fee-fi-mo-manna</cf_thing>
	<cf_thing>Anna!</cf_thing>
</cf_thing-group>

<hr />

<cfmodule name="ui.thing-group" style="cfmodule[name]">
	<cfmodule name="ui.thing">Anna</cfmodule>
	<cfmodule name="ui.thing">Anna</cfmodule>
	<cfmodule name="ui.thing">Bo-banna</cfmodule>
	<cfmodule name="ui.thing">Banana-fanna fo-fanna</cfmodule>
	<cfmodule name="ui.thing">Fee-fi-mo-manna</cfmodule>
	<cfmodule name="ui.thing">Anna!</cfmodule>
</cfmodule>

<hr />

<cfmodule template="./tags/ui/thing-group.cfm" style="cfmodule[template]">
	<cfmodule template="./tags/ui/thing.cfm">Anna</cfmodule>
	<cfmodule template="./tags/ui/thing.cfm">Anna</cfmodule>
	<cfmodule template="./tags/ui/thing.cfm">Bo-banna</cfmodule>
	<cfmodule template="./tags/ui/thing.cfm">Banana-fanna fo-fanna</cfmodule>
	<cfmodule template="./tags/ui/thing.cfm">Fee-fi-mo-manna</cfmodule>
	<cfmodule template="./tags/ui/thing.cfm">Anna!</cfmodule>
</cfmodule>

<hr />

<cfimport taglib="./tags/ui" prefix="ui" />

<ui:thing-group style="cfimport[ui:]">
	<ui:thing>Anna</ui:thing>
	<ui:thing>Anna</ui:thing>
	<ui:thing>Bo-banna</ui:thing>
	<ui:thing>Banana-fanna fo-fanna</ui:thing>
	<ui:thing>Fee-fi-mo-manna</ui:thing>
	<ui:thing>Anna!</ui:thing>
</ui:thing-group>

In this ColdFusion code, we're using the four custom tag reference mechanics:

  1. The cf_ prefix.
  2. The cfmodule[name] tag.
  3. The cfmodule[template] tag.
  4. The cfimport tag (a compile-time directive).

When we run this ColdFusion code, we get the following output:

Successful rendering of the ColdFusion code showing several unordered lists.

As you can see, all of the various ColdFusion custom tag mechanics were able to use the (-) in the thing-group.cfm identifier. Again, it doesn't read quite as nicely as the Flux UI's dot-based name-spacing; but, I think it would work just as well.

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

Reader Comments

15,969 Comments

As an aside, I can't believe that the CFImport tag is still a compile-time directive (presumably because of some of the JSP integration stuff?). I would love to have a version of the tag, or even a new tag such as cfnamespace, that would allow me to prefix custom tags using per-application path mappings.

To this end, I've submitted a feature request in the Adobe bug tracker: CF-4225709.

The hope is to be able to have something like this:

<cfnamespace prefix="ui" directory="/per/app/mapping">

<ui:my-tag>
	<ui:another-tag />
	<ui:another-tag />
	<ui:another-tag />
</ui:my-tag

This is already how cfimport works; only the taglib (in cfimport) cannot use per-application mappings. This would be a tag that does nothing more than make prefixing available via per-app mappings.

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