Using CustomTags in ColdFusion

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:

<cfoutput>#DateFormat(Now(), "mm/dd/yyyy")#</cfoutput>

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:

<cf_todaysdate>

Using attributes

To 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. The 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 thisTag.generatedContent.

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 thisTag.generatedContent variable:

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.



19 people found this page useful, what do you think?

 Download FuseGuard WAF for ColdFusion

Trackbacks

Trackback Address: 64/E8FD80AD9D6A5A038B66B84AF587732D

Comments

On 04/02/2010 at 2:24:29 AM EDT Paolo wrote:
1
Hi Pete

Hi

I would like to wrap certain blocks of code in my app with a CFTRY and CFTRANSACTION so that the code looks like this:

<cftry> <cftransaction action="begin"> <!--- Custom Code ---> <cfcatch> <!--- Custom logging ---> <cftransaction action="rollback"> </cfcatch> <cftransaction action="commit"> </cftry>

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: <cftry> <cftransaction action="begin">

And in the TryTransactionEnd Tag you will have: <cfcatch> <!--- Custom logging ---> <cftransaction action="rollback"> </cfcatch> <cftransaction action="commit"> </cftry>

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?

Post a Comment




  



Spell Checker by Foundeo

Recent Entries



foundeo


did you hack my cf?