DEV Community

James Moberg
James Moberg

Posted on • Edited on

CustomTag CFScript "Nuance"

I still have some CustomTags that we've used in production for years and, now that I'm writing more cfscript, I thought I'd continue using some of them (for now) using the following syntax that I learned about on StackOverflow:

CFML tag-based approach:
<cf_customTagName param1=param1Value>

CFScript approach:
cf_customTagName(param1=param1Value);
Enter fullscreen mode Exit fullscreen mode

I immediately discovered that the cfscript method was executing the tag twice. In order to execute the tag-based version twice using CFML tag-based syntax, you need to explicitly use a starting and closing tag and then check for thisTag.executionMode with a value of either start or end.

<cf_customTagName param1=param1Value>
    <!--- this runs the tag twice w/different executionModes --->
</cf_customTagName>
Enter fullscreen mode Exit fullscreen mode

The "nuance" (that CFM-based custom tags are always executed twice twice via cfscript) isn't documented on the only Adobe documentation that discusses this: "Script support for custom tags". (NOTE: I'm not sure if this behavior is the same in Lucee CFML.)

The solution for this is check whether the CFM file is being executed as a CustomTag (ie, if thisTag.executionMode exists and is start) and then exit.

<cfif isDefined("thisTag.executionMode") and thisTag.executionMode is "start">
    <cfexit>
</cfif>
Enter fullscreen mode Exit fullscreen mode

If you don't explicitly do it this way, you'll risk having the customtag's functions unknowingly performed twice which can cause data problems or negatively impact performance.

Here's the files I set up to reproduce and test this:

https://gist.github.com/JamoCA/2d48f9eb88ceb7f8bcb93fc3ab718ffa

Top comments (3)

Collapse
 
bennadel profile image
Ben Nadel

On the Lucee CFML side, I've run into some quirky behaviors trying to get Custom Tags to run in CFScript. Since Lucee allows all tags to be run in script by essentially removing the cf prefix,

Example, <cfthread></cfthread> becomes thread { .. }

Example, <cfhttp></cfhttp> becomes http { .. }

... I think you can actually run a custom tag by just removing the cf.

Example, <cf_helloCount></cf_helloCount> becomes _helloCount { .. }

With, admittedly, looks strange :D But, there's some strange syntax parsing issues (if I remember correctly it's related to trying to run the tag on a single line vs. with line-breaks around attributes).

Also, I don't believe I've found a way in either engine to use the Prefix feature of custom tags' interplay with <cfimport>. I'm pretty sure that neither engine likes the syntax:

prefix:tag { ... }

I love CFScript, but I've been sticking to tags for custom tag usage.

Collapse
 
giancarlogomez profile image
Giancarlo Gomez

On ACF it will also execute twice if you use a self-closing tag, which I would pretty much always do and due to that I always got used to writing them with the execution mode check.

<cf_customTagName param1="param1Value" />

Collapse
 
gamesover profile image
James Moberg

Yeah... I've been careful to not self-close CustomTags. I didn't expect cfscript to treat it as a closed tag as there's a specific syntax for that.