DEV Community

James Moberg
James Moberg

Posted on ā€¢ Edited on

1 1

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

<!--- 20220718 CustomTag CFScript "Nuance"
Blog: https://dev.to/gamesover/customtag-cfscript-nuance-4nig
Tweet: https://twitter.com/gamesover/status/1549111965523386368
--->
<p>This executes the custom tag only one (1) time.</p>
<cf_helloCount>
<P>When called from cfscript, this CFM-based custom tag is executed twice.</p>
<cfscript>
cf_helloCount();
</cfscript>
view raw custom-tag-test.cfm hosted with ā¤ by GitHub
<cfparam name="request.timesCalled" default="0">
<cfset request.timesCalled +=1>
<cfoutput>
<p>Hi! (Times called: #request.timesCalled#)</p>
</cfoutput>
view raw helloCount.cfm hosted with ā¤ by GitHub

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

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.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

šŸ‘‹ Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay