Using CustomTags in ColdFusion
Using custom tags in the presentation layer can greatly organize your code. Here's a quick start guide that I wrote up. Building a simple ColdFusion custom tag is as easy as:
A simple custom tag
create a file called todaysdate.cfm:
Then place todaysdate.cfm in ColdFusion server's CustomTags directory, or in the same directory that you will call it from. To call it simply create a page with the following:
Using attributesTo pass an attribute into a tag, is also fairly easy.
greet.cfm: <cfparam name="attributes.name" default="Dude" type="string"> <cfoutput>Hello #attributes.name#!</cfoutput> Now to call it: <cf_greet name="Pete">
In the greet tag there is an attribute called "name" which we passed the value "Pete" to in our example. We can access attributes using the
attributes scope, attributes.attributename. In this tag we used the
<cfparam> tag to set the default value of the name attribute to "Dude".
Using start and end tags
Another thing you can do with custom tags is to use start and end tags. Something like this:
<cf_myTag> This is some content </cf_myTag>
To access the content inside the tag we use another scope called
thisTag scope contains variables that hold information about the tag that is being executed, such as the content between the start and end tags. Such content may be accessed with the variable
Because you may want to do some processing when the start tag is invoked, and then some more when the end tag is invoked, your custom tag will file will be executed twice when you use an end tag. Luckily you can use the variable thisTag.executionMode to determine if your currently executing the start tag or the end tag. Lets consider a highly trivial example, of creating a ColdFusion tag to make text bold, there are several ways we can do this. Here is the simplest:bold.cfm:
<cfif thisTag.executionMode IS "start"><b><cfelse></b></cfif>
The above tag will output a <b> tag when the start tag executes, and a </b> tag when the end tag executes.
Another way of solving this problem is to use the
bold.cfm: <cfif thisTag.executionMode IS "end"> <cfset thisTag.generatedContent = "<b>" & thisTag.generatedContent & "</b>"> </cfif>
In this case we are resetting the value of
thisTag.generatedContent to include the <b> tags. When the end tag is finished executing ColdFusion will output the contents of thisTag.generatedContent.
Note that the value of
thisTag.generatedContent is not set until the end tag begins executing. Setting the value of it in the start tag execution mode will have no effect on the output.
A third way to solve this problem is similar to the last, but in many cases this will be the way to go:
bold.cfm: <cfif thisTag.executionMode IS "end"> <cfoutput><b>#thisTag.generatedContent#</b></cfoutput> <cfset thisTag.generatedContent = ""> </cfif>
In this example your handling the output yourself, and setting the value of
thisTag.generatedContent to an empty string. This is the way to go if your using a lot of conditionals to produce your output.
A few more tricks we can use to ensure that our tag is being called properly include:
To ensure that the end tag is present:
<cfif thisTag.executionMode IS "end"> Do something. <cfelseif NOT thisTag.hasEndTag> <cfthrow message="Missing end tag."> </cfif>
To ensure that the file is only called as a custom tag:
<cfif NOT IsDefined("thisTag.executionMode")> Must be called as customtag.<cfabort> </cfif> <cfif thisTag.executionMode IS "end"> Do something. <cfelseif NOT thisTag.hasEndTag> <cfthrow message="Missing end tag."> </cfif>
Update 4/4/03:Ray Camden also suggested this handy code snippet:
To ignore an end tag:
<cfif thisTag.executionMode is "end"> <cfexit> </cfif>
That code simply ignores the end tag. This is useful if your trying to use valid XML within your CFML, such as
<cf_mytag />. Many people have gotten in the habit of doing that now, but keep in mind that CFML is not valid XML, mainly CFIF statements tend to break the rules.
I would like to wrap certain blocks of code in my app with a CFTRY and CFTRANSACTION so that the code looks like this:
<!--- Custom Code --->
<!--- Custom logging --->
But I want to add the code to custom tags so that I minimise code and centralise all the logging to one place. Something like:
<cfmodule name="TryTransactionStart" />
<!--- Custom Code --->
<cfmodule name="TryTransactionEnd" />
Then in the TryTransactionStart tag you will have:
And in the TryTransactionEnd Tag you will have:
<!--- Custom logging --->
I have tried this, but obviously Coldfusion is complaining about the cftry and cftransaction tags requiring closing tags when I run it.
Is this possible?
- Upcoming CFML Conferences in April 2017
- CFSummit 2016 Slides
- Securing Legacy CFML - dev.Objective() 2016 Slides
- My CFSummit 2015 Slide Decks
- Adding Chrome Custom Search for CFDocs
- Disable Flash Remoting on ColdFusion Servers
- HackMyCF Adds SSL/TLS Scanner
- IncompatibleClassChangeError after ColdFusion 11 Update 5