(Re-) Introducing Layout Components

I have been using the same approach for site layout code for about five years. I have written about it a little bit in the past, but I decided (finally) that it made sense to package it up as a download and write some real documentation around it.

If you are already using an MVC framework on a project then it probably has a solution for layouts backed-in, if not then I would recommend taking a good look at Layout Components. They make layouts easy without introducing any of the challenges that usually come with layout solutions.


CodeCop and Layout Components

CodeCop has reached release candidate stage. I am still not thrilled with my installation code, but it works pretty well. It also makes for a good example of using several of my components (including layout components and DataMgr).

CodeCop will check your code and report possible problems. The rules that it uses to determine possible problems are completely configurable from within CodeCop itself. You can also share rules packages with other developers (I am hoping to set up a place to facilitate this sharing on my site soon). 

If you have a suggestion for keeping the installation as clean and user-friendly as it is, but make the code cleaner, I would be interesting in hearing it (look in install.txt to see the installation instructions).

CodeCop uses the DataMgr 2.0 (which is still in Beta - hoping to get that into release candidate stage before the end of the year) as well as layout components.

I hope to have a full entry on using layout components out later this week (was hoping to include that in this entry, but running out of time). 

Managing the UI

Peter Bell has an interesting series on "Architecting Your Views". As usual, his thoughts are very interesting and inpsired me to share my own views on the matter.

Peter starts by referencing my article on layout components and then describes his requirements for a CMS. In brief, they are:

  • Page Templates
  • Multiple Dynamic Content Areas
  • Reusable Screens
  • Extensible UI Components
  • Snippets
  • Separation of Concerns
  • Declarative Specification

I think that the distinction between a CMS and a site layout is an important one. Layout components can help with some (but not all) of these requirements. Many of them, however, are outside the scope of what your layout mechanism should provide.

Layout components can help with page templating by providing an easy mechanism to switch to a different layout.

In order to use my "Home" layout (as opposed to, perhaps, my default one), I add the following code above my call to the layout component.

<cfset layout = layout.switchLayout("Home")>

No reason why that couldn't be a dynamic value from the CMS instead of a hard-coded "Home" as well. 

Most of the remaining functionality isin the domain of the CMS, but I do want to touch on a few other points that I will combine in one basic topic.

Snippets and Extensible UI Components are both reusable visual elements. Peter uses a Render component while many other people use custom tags. I think this brings up an important distinction. Some UI components are inherently general in purpose while others are intrinsically tied to the layout.

For example, every administrative section I have worked on needs tables and forms with similar functionality. As such, I have custom tags to manage each (available on my site, but still need to be cleaned up a bit). On the other hand, a given site may have a small calendar widget that will be used in various places throughout the site. It won't be used on other sites, but will need to be used in various places on this one.

In that case, I often add a method to my layout component. In this example, I would add a calendar() method which would render the calendar component. This also allows the calendar method to be extended for different layouts. For example, it might show up in the Home or Default layout, but not the layout used for outputting to MS Word.

I think that the Render component idea has some promise, but also may be more complex than is often needed. Most significantly, however, I think the distinction between general UI components and components that are essentially a part of the layout is an important distinction.

Incidentally, if you would like to see a full-fledged example of layout components at work, check out CodeCop (which will also review your code and which - thanks to layout components - looks right in CF6 admin, CF7 admin, or on its own). It is still in beta, but makes for a pretty good example of layout components (as well as the previously mentioned custom tags).

Header and Footers

A few years ago, I was working on my first non-Fusebox site (by client requirement). I handled layouts (with some modification) by calling the requested file from Application.cfm and then outputting the results in the site layout.

I created a file for decisions about which files should get which layout and I made some exceptions for some pop-up pages.

This seemed to work well, overall. I had a centralized layout file (similar to what I would have had in Fusebox 3). I could make universal changes to the layout in one place. I was able to integrate it with a Fusebox 2 shopping cart that we had chosen for the site.

I recently added some new functionality. Due to time constraints, I subcontracted out the work. I got back an AJAX tool to be used in the site administration. I tested it out and it worked as specified. I copied it into the site and tried it out. It looked right, but the AJAX would never return any results.

The reason, of course, is that the AJAX results were being returned with the layout applied to them. OK. No problem. I went in to the configuration page and made another exception for the AJAX data results. Of course, because I had written the site so long ago it took me a while to figure out the problem.

The site uses a slightly different layout for the home page than for the other pages. So, I create a copy of the home page to test changes. Each time, I have to remember to make an exception for the home page so that it gets the home page layout instead of the default one.

None of these issues are major, but they are still problems.

The problems all stem from a very basic issue: The decision of which layout to use on a page is being made outside of the page itself. If the page made th decision of which layout to apply then it would keep the layout when I copied the home page. If the page made the decision of which layout to use, then the AJAX data pages would have worked, never having had any layout applied to them.

This seems like a lot of work, but it doesn't have to be. If you use cfinclude for headers and footers, you just need to do the include from within your page rather than from Application.cfm and OnRequestEnd.cfm (or Application.cfc).

Personally, I find layout components to be the easiest approach for handling layout issues, but cfinclude is one of several other viable options. The main point here is that a page should make its own decision about which layout (if any) it should use.

In Defense of CFCs for Output

A just read a comment arguing against output CFCs as more difficult to maintain than Custom Tags. As this differs somewhat from my experience, I wanted to explore the idea.

In a comment to blog entry by Terrence Ryan, Sean Corfield said that he thought designers could edit Custom Tags easier than CFCs. This because they could use their WYSIWYG editors on the custom tags.

I agree if the output is limited to a small widget. If the output is the for the layout (the overall design) of the page, however, I would disagree.

My problem with using Custom Tags for layout comes from the need to have different parts of the design in different custom tags (or using an awkward "action" attribute).

Using Output CFCs allows me to have the layout in only one file - which just like an HTML file of the design (once you ignore the cffunction tags - easy to do). This is easy to edit for anyone that knows HTML. For others, you could save it as a .html file for WYSIWYG editing and back again (though I have yet to have that need).

This is far outweighed by the advantages of this approach. Among them having all of the layout in one file, the ability to easily switch between different layouts, the ability to easily switch to different output formats (PDF,Word,etc), and the ability to easily gain control over the <head> for any page.

Since I am too lazy to rehash these benefits completely, I will just point you to my article on Handling Layouts with Components. Feel free to download some example layout components as well.

Note that if you are worried about the performance implications of this approach, Terrence Ryan's blog entry covers that pretty well. Of course, he isn't using the exact approach that I am, but I think the point remains valid.

BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.