ColdFusion MX and Code Reuse: Custom Tags
One of the coolest ways in which you can create code for reuse with ColdFusion is through the use of CFML custom tags. These custom tags enable you to create snippets of code that perform a very specific function and then use that code again and again throughout your applicationall without having to rewrite the source code.
At first glance, creating your own custom tags to help modularize your code might seem like a daunting task. However, after you begin to understand how ColdFusion processes these tags, you'll be amazed at how simple the entire process can be.
To demonstrate the concept, let's create a hypothetical situation. Your boss has told you that on all pages throughout your corporate intranet, she wants to see an "Updated by so and so, on such and such a date" line of text so that she can tell when pages were last modified and who made the modification.
Obviously, each member of your intranet team responsible for creating and updating content could go into the source files each time they were modified and create or edit the following line of Hypertext Markup Language (HTML) code:
<H3><I>Last modified by Joe User on April 26, 2002</I></H3>
Although this might work for a while, it might not be the best way to do things. For instance, a programmer could inadvertently damage this line of code as he was modifying it.
Note also that an include wouldn't be the best way to handle this problem because the name of the user modifying the page might differ from page to page, and using an include would affect the intranet globally.
Fortunately, we can create a simple CFML-based custom tag to solve our problem. Take a look at the following code example, which creates the simple customer tag "CF_ModifiedBy". We'll then look at how to use this tag:
<!---Name: ModifiedBy.cfm Description: Enables us to change the "modified by" footer at the bottom of all of our intranet pages. Author: Joe Programmer Date: 4-26-2002 Attributes: ModifiedBy: (Required) Specifies the name of the person who is modifying the HTML code. DateModified: (Required) Specifies the date that the Document is being modified.---> <cfparam name="attributes.modifiedby" default=""> <cfparam name="attributes.datemodified" default=""> <!---If a required parameter does not have a value passed in, stop processing and throw an error.---> <cfif NOT Len(attributes.modifiedby) OR NOT Len(attributes.datemodified)> <cfabort showerror="You must enter both your name and the date as attributes!"> </cfif> <cfoutput> <h3><i>Last modified by #attributes.modifiedby#, on #attributes.datemodified#</i></h3> </cfoutput>
We've created our simple CFML custom tag. Now when someone wants to create a new CFML template that changes the modified-by line displayed at the bottom of the page, he or she can do it by adding this custom tag to the source of the CFML template, as in the following example:
<HTML> <HEAD> <TITLE>Sample Intranet Page</TITLE> </HEAD> <BODY> ----SOME CODE---- <CF_ModifiedBy ModifiedBy="Joe Programmer" DateModified="April 26, 2002"> </BODY> </HTML>
After this code is in the source CFML, you can see how easy it is to go back in and change the ModifiedBy or DateModified attributes. This is certainly much easier than rewriting the respective line of code for every CFML document in which it needs to appear.
Now that you understand why you'd want to use CFML custom tags and how they are written, it helps to know how ColdFusion processes these tags.
When you create a CFML custom tag, you name it as you would any other CFML template. As in the previous example, the ModifiedBy tag was simply called ModifiedBy.cfm. By the way that we call it from within our CFML code, ColdFusion knows that we intend for this file to be used as a custom tag. By appending CF_ to the beginning of the template name, omitting the .cfm extension, and enclosing the name in <>, we are signaling to ColdFusion that we are about to invoke a custom tag.
Thus, to call a file named ModifiedBy.cfm as a CFML custom tag, we would place the following line of CFML in the calling template:
<CF_ModifiedBy>
After your custom tags are written, you can place them in the directory from which you are going to call them, or you can put them in a central custom tags directory. Placing custom tags in a central custom tags directory is the recommended method of storage. It provides a simple, easy-to-find repository for all your modular code. By default, this custom tag's directory is CFUSIONMX/CustomTags.
As you saw in our simple example, you can pass attributes into the custom tag from the calling page. After these variables are passed to the custom tag, you reference them by using the attributes scope. This helps differentiate variables being passed into the custom tag from those that are local variables within the custom tag.
Appending any attribute/value pair to a custom tag call causes that attribute/value pair to be passed into the custom tag. As an example, if we were using the CF_ModifiedBy tag in a CFML template, we might call it in the following manner:
<CF_ModifiedBy ModifiedBy="Joe Programmer" DateModifed="April 26, 2002" FavoriteColor="Green">
In this case, all the following attribute/value pairs are passed into the custom tag:
ModifiedBy=Joe Programmer DateModified=April 26, 2002 FavoriteColor=Green
Of course, our custom tag is written to make use of only the ModifiedBy and DateModified attributes, so the FavoriteColor attribute is ignored. Nonetheless, it is still important to know that it is present in the attributes scope.
If you want to make a specific attribute a "required" attribute, you can write logic within the custom tag to ensure that all required attributes get passed in. You can see in our CF_ModifiedBy example that we have done this by using CFIF statements to ensure that if the ModifiedBy and DateModified attributes are not present, we stop processing and present the user with an appropriate error.