How I Create Custom CFML Tags
13 Sep 2010Resources
While I was cleaning up some code in a portal of ours, I realized that I could condense some of the code by combining a variable assignment with a custom tag attribute assignment.
To make things simple, the tag I am trying to optimize creates a database record with a note assigned to it.
1 <cfset notes="A ton of html code here.">
2 <cf_my_tag notes="#notes#">
The issue is that this code wouldn’t necessarily add a note in the same manner, every time. There might be times where I have to build the notes in a loop before I run the tag. Then there are times where I want to run the tag and NOT add a note. Also, I might want to define the note directly in the tag contents.
So here are the requirements for my new custom tag:
- The tag must be willing to accept an attribute named “notes”
- The tag must be willing to run without defining “notes”
- The tag must be willing to transform its contents into “notes”, if it is not empty.
With the above constraints in mind, here’s what I came up with.
1 <!--- Content of my_tag.cfm --->
2 <cfscript>
3 param ATTRIBUTES.notes = "";
4 if (ThisTag.hasEndTag) { // Closable Tag
5 if (ThisTag.ExecutionMode EQ "start") {
6 // ThisTag.GeneratedContent is not set yet.
7 } else {
8 // This is the best place to execute code
9 // All possible 'ThisTag' variables are defined.
10 if (ThisTag.GeneratedContent NEQ '') {
11 // GeneratedContent takes priority over attribute
12 ATTRIBUTES.notes = ThisTag.GeneratedContent;
13 }
14 engage();
15 }
16 } else {
17 // Self-standing Custom Tag
18 engage();
19 }
20 </cfscript>
21
22 <cffunction name="engage">
23 <cfscript>
24 // Capture Generated Content
25 // (if we need to refer to the original content)
26 LOCAL.content = ThisTag.GeneratedContent;
27
28 // Prevent browser display of GeneratedContent
29 ThisTag.GeneratedContent = "";
30 </cfscript>
31
32 <!--- Do Stuff Here --->
33 </cffunction>
This setup fulfills all three requirements:
- I can refer to the ATTRIBUTES.notes variable to insert my note.
- I don’t need to define ATTRIBUTES.notes as it is param’ed at the top of the tag.
- If I have a closing tag with a non-empty string for its GeneratedContent, the ATTRIBUTES.notes variable will be overwritten with the GeneratedContent. This works for self-closing tags as well.
- It also allows me to place my logic into a single function rather than splitting it up in an if..else block.
So there you have it. A simple solution to create a custom tag with flexible closing tags.
Happy Coding!