Skip to main content
Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.

Expected And Unexpected getBaseTagData() Behavior In Lucee CFML 5.3.7.47

By Ben Nadel on
Tags: ColdFusion

In the implementation details of my ColdFusion custom tag DSL for HTML emails, I have to access the data exposed by ancestor custom tags. In some cases, the parent tag is dynamic; which means that I have to use the getBaseTagList() function in order to figure out the name of the ColdFusion custom tag that I need to access. It turns out that some native ColdFusion tags show up in the getBaseTagList() value; but, they do not expose any "data". As such, they have to be explicitly skipped-over. Things get even more complicated when you use CFModule to invoke a custom tag. And, since I stumbled over this in my journey, I figured it might be worth a quick demo in Lucee CFML 5.3.7.47.

One way in which a ColdFusion custom tag can communicate with another ColdFusion custom tag is by using the getBaseTagData(). This allows one tag to reach up into the variables scope of another tag to read-from or write-to various data structures. But, calling getBaseTagData() doesn't always work, depending on the type of tag and the way in which the tag was invoked.

To see this in action, I have a test page that nests some native ColdFusion tags and some custom tags. Notice that one custom tag in particular - Wrapper.cfm - is in there twice: once using the CF_ notation and once using CFModule:

<cfsavecontent variable="content">
	<cf_Wrapper>
		<cftimer type="outline">
			<cfmodule template="Wrapper.cfm">
				
				<cf_MyTag />

			</cfmodule>
		</cftimer>
	</cf_Wrapper>
</cfsavecontent>

<cfset echo( content ) />

The cf_MyTag tag is our ColdFusion custom tag that is going to try and walk up the tree of tags and access the data attribute. Each tag will be accessed in a try/catch so that we can see which worked and which didn't:

<cfscript>

	dump( label = "Base Tag List", var = getBaseTagList() );

	// Loop over each item in the base-tag list and try to access the "Data".
	// --
	// CAUTION: This does NOT WORK. Native ColdFusion tags show up in this list but they
	// DO NOT expose tag data the way that custom tags do.
	loop
		item = "parentTagName"
		list = getBaseTagList()
		{

		echo( "<br />" );

		try {

			dump( label = parentTagName, var = getBaseTagData( parentTagName ) );

		} catch ( any error ) {

			dump( "Oh Noes! getBaseTagData( #parentTagName# ) failed!" );

		}

	}

	exit method = "exitTag";

</cfscript>

As you can see, there's nothing special going on here - we're just walking the list of ancestor tags and trying to access the data. And, when we run this ColdFusion code in Lucee CFML, we get the following output:

An attempt to access ColdFusion custom tag base data in Lucee CFML.

Ok, so the first take-away here is that some native ColdFusion tags show up in the getBaseTagList(). If I had to guess, I'd say that it's any tag that is concerned with "wrapping content". For example, while I didn't test it, I would guess that the CFXML tag also shows up in this list since it wraps and parses content.

These native ColdFusion tags should be skipped when dynamically accessing a parent custom tag. In fact, I assume that the only tags that can be accessed are those with the CF_ prefix. Which brings us to the second and arguably much more important lesson: ColdFusion custom tags do not expose data when invoked using CFModule (in Lucee CFML).

If you refer back to test.cfm above, you'll see that the Wrapper.cfm template is in the demo twice:

  • <cf_Wrapper>
  • <cfmodule template="Wrapper.cfm">

And, while this is the same exact tag, getBaseTagData() only works when the tag was invoked using the CF_ prefix, not when using the CFModule tag. This may be related to an earlier issue I posted in which I demonstrated that getBaseTagList() and the CFModule tag works different in Adobe ColdFusion vs. Lucee CFML.

ASIDE: ColdFusion custom tags will also expose data when invoked using the CFImport tag. This is the basis of how my ColdFusion custom tag DSL for HTML emails works - it's CFImport tags all the way down!

Now, if we run similar code in Adobe ColdFusion 2018 (the syntax had to be modified), we get the following output:

An attempt to access ColdFusion custom tag base data in Adobe ColdFusion.

As you can see, with Adobe ColdFusion 2018, the Wrapper.cfm exposes data regardless of the way in which it was invoked (CF_ prefix of CFModule tag). However, when we look at the output of the getBaseTagList(), we see a potentially key difference:

  • Lucee CFML: CF_MYTAG, CFMODULE, CFTIMER, CF_WRAPPER, CFSAVECONTENT

  • ACF 2018: CFDUMP, CF_MYTAGACF, CF_WRAPPER, CFTIMER, CF_WRAPPER, CFSAVECONTENT

In Adobe ColdFusion, the Wrapper.cfm template shows up as CF_WRAPPER regardless of the invocation approach. This speaks to my earlier post about the difference in engines; and, it may be the underlying root cause of the problem. Perhaps Lucee CFML won't even check for base-tag data unless the invocation "expression" starts with CF_?

I'll add this finding as an additional note in the compatibility bug that I filed on the Lucee JIRA server.



Reader Comments

What has two thumbs and hopes you leave a comment? This Guy! (Ben Nadel).

Post A Comment

You — Get Out Of My Dreams, Get Into My Blog
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.