More Model-Glue Rumblings... Layouts within Layouts

As I continue to work on the new version of CFLib (and I promise this week I’ll put the beta version up so folks can look at, and laugh at, my mistakes), I wanted to tackle a new problem that I was a bit unsure of how to handle.

Take a quick look at CFLib. Notice the layout doesn’t change as you go from page to page. This layout was easily put into a view in the MG version. But notice the “pods” in the right hand section. By “pod” I mean each little box. This part confused me a bit. How could I get these guys into my layout? I had already moved my layout to an event by itself:

<event-handler name="Layout">
   <views>
   <include name="main" template="layout.main.cfm" />
   </views>
</event-handler>

This layout template simply checked the viewCollection for a value called body. Each of my events used “body” when doing their views. How then would I add in my pod? MG lets you stack views, allowing the later views to include the content from the earlier views. So if I wanted to simply include the HTML for the pods, it would be rather simple. I’d just add a new include tag.

However - I wanted to abstract the pod view as well. This turned out to be rather simple:

<include name="podbody" template="dsp.searchpod.cfm" />
<include name="pod" template="layout.pod.cfm">

My search pod, for now, was rather simple:

<cfset viewState.setValue("podtitle","Search CFLib.org")>

<cfoutput>
This is the search pod.
</cfoutput>

Note the use of the viewState to set my title. This let me pass a title to my pod. So far so good. My pod view code had HTML and this:

<cfif viewCollection.exists("podbody")> #viewCollection.getView("podbody")# </cfif>

Everything ran fine until I added another pod:

<include name="podbody" template="dsp.searchpod.cfm" />
<include name="searchpod" template="layout.pod.cfm" />
<include name="podbody" template="dsp.logonpod.cfm" />
<include name="logonpod" template="layout.pod.cfm" />

The first thing I forgot was the views with the same name will overwrite each other. So my 2 podbody tags would not work. The first thing I did was give better names to my two pods, “searchpodcontent” and “logonpodcontent”. However, my view for th epod was still checking for “podbody”. How could I tell my view what viewCollection to use? I then remembered that I could pass an argument to my views. I switched to this:

<include name="searchpodcontent" template="dsp.searchpod.cfm" />
<include name="searchpod" template="layout.pod.cfm">
   <value name="podcontent" value="searchpodcontent" />
</include>
<include name="logonpodcontent" template="dsp.logonpod.cfm" />
<include name="logonpod" template="layout.pod.cfm">
   <value name="podcontent" value="logonpodcontent" />
</include>

With me so far? My pod layout would simply check the viewState to get the name of the content to load:

<cfset contentName = viewState.getValue("podcontent")>
(lines of html and junk)
<cfif viewCollection.exists(contentName)>
    #viewCollection.getView(contentName)#
</cfif>

So far so good. However, now I had a new problem. Both pods rendered. But the second pod had the right title and the wrong content. Turns out - I was thinking of the VALUE tag as an argument to a UDF - where it’s really meant to set a value in the viewState data structure. Therefore, the value wasn’t unique. All I had to was tweak the value tag to pass overwrite=”true”. And a big thank you to Joe R. for pointing that out to me. Here is the final version of the event from my MG xml file:

<event-handler name="Layout">
<views>
   <include name="searchpodcontent" template="dsp.searchpod.cfm" />
   <include name="searchpod" template="layout.pod.cfm">
      <value name="podcontent" value="searchpodcontent" />
   </include>
   <include name="logonpodcontent" template="dsp.logonpod.cfm" />
   <include name="logonpod" template="layout.pod.cfm">
      <value name="podcontent" value="logonpodcontent" overwrite="true"/>
   </include>
   <include name="main" template="layout.main.cfm" />
</views>
</event-handler>

Now - some MG experts out there are yelling, “No Ray, there is a better way!” One of the things I love about ColdFusion is that there is always a better way. I’ve had a few suggestions sent to me, and later today I’ll blog about them.

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. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Comments