Ask a Jedi: Getting a bit fancier with a layout custom tag

John asks:

Somewhere about a year ago, I found an article on using a layout.cfm page "custom tag" to layout the template for the site. I include a header, menu and footer. I wrap this around all my pages and volia we have a fairly robust template engine. Only now with all the power of the cfc and a huge whole in my plan, I need a new way to do this layout. I need to be able to create different layouts in the content area, but make them reusable through out the site. With the simple cfcase value="start" and end option I do not have a way to specify the or dynamically call a different layout page without having to write an entire new layout page with that code in there. If that is the best way I can do that but, there has to be a way to make it and I can not wrap my brain around that process.

So normally I don’t worry too much about completely different templates. Most sites I’ve worked on will use one main layout with perhaps just a few variations. The inner content may move from two columns to one column perhaps. To handle cases like that, I simply add new attributes to my custom tag to let me specify which to use, and I try to gauge which layout is used most often and make that the default.

But how would you handle a case where the layout you want is really varied? As always, there are a few things to consider. One simple way is to just use multiple custom tags. So you may have a productlayout.cfm and a reviewlayout.cfm file. This works ok if your file has a hard coded template. I.e., if you always know foo.cfm is a product page, you wrap it with productlayout.cfm. But again - that’s hard coded and won’t always be appropriate, especially if you want the layout to be chosen by a non-technical user who doesn’t want to edit code.

Another possible way of doing this is demonstrated in Galleon. For that project I created a layout custom tag that takes a template attribute. The code for this tag is here:

<!--- Because "template" is a reserved attribute for cfmodule, we allow templatename as well. ---> <cfif isDefined("attributes.templatename")> <cfset attributes.template = attributes.templatename> </cfif> <cfparam name="attributes.template"> <cfparam name="attributes.title" default="">

<cfset base = attributes.template>

<cfif thisTag.executionMode is “start”> <cfset myFile = base & “_header.cfm”> <cfelse> <cfset myFile = base & “_footer.cfm”> </cfif>

<cfinclude template=”../pagetemplates/#myFile#”> </code>

This layout tag takes a templatename or template attribute (I use both since template is reserved in cfmodule). This points to the base file name inside a pagetemplates folder. So if I request templatename=”main”, the code will either load main_header.cfm or main_footer.cfm based on the execution mode. This lets me do stuff like this:

<cf_layout template="main"> ... </cf_layout>


<cf_layout template="#session.mylayout#"> ... </cf_layout>

Again - this is just one example of how it could be done.

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support.

Lafayette, LA