I’ve always been a big fan of keeping things that belongs together, together. This might be an obvious fact, but I sometimes find that in Sitecore, it’s not so easy to follow. If you read my post on agile Sitecore design, you’ll get my drift. But this post is on something much more practical, i.e. composing your layouts in Sitecore, and how something I choose to call composite layouts can help you make your practice better.
When it comes to putting your pages together in Sitecore, you have two choices:
You can choose to build up your entire page composition on your templates in Sitecore, i.e. choose a layout and putting all sublayouts, renderings etc. on a template (which is naturally the __standard values of the template). This method is in my book the most correct, as it allows you, your fellow developers and the administrators to see the complete structure of a page, without leaving Sitecore. Unfortunately Sitecore does not deliver any layout inheritance etc., so this way requires a lot of hard work and mouse clicking (“try adding a rendering to all pagetypes late in the process – phew”) and is potential place for mistakes. Also, the page designer and Webforms module copies the layout from the template, locally to the item – and trust me, you do not want your layout with 20 renderings spread over your 15 pagetypes and 356 local items (“try adding a rendering to all pagetypes late in the process – double-phew”).
So, unless you are committed to keeping your page composition in one place, and choose not to use the page designer and webforms, you are left with the second option – putting page composition in sublayouts. This is where you put renderings and other sublayouts directly in the .ascx file, either through Visual Studio or the Sitecore layout designer. The big problem I have with this option, is that you separate page composition into two places – Sitecore and the ascx files. This forces you to use two different systems to setup caching etc. and makes it difficult to overview the complete page composition.
Enter Composite Layouts:
Composite Layouts is a new type of rendering I developed for a large project, which bridges the gap between the two options. It utilizes the fact that even rendering items in Sitecore have a Layout field, and it merges a layout set directly on a composite layout item into the layout set on a template. I.e. a composite layout is pretty much like a sublayout, in that it allows you to group renderings and place them on a page as a unit. The exception is that all configuration is done in Sitecore and the renderings on a composite layout can be placed in all placeholders – even placeholders outside the composite layout.
Our Form pagetype is a standard document page (with the usual header, topmenu, title, leftmenu, footer, spots etc.) which renders a selected form (which is incidentally created using Webform for Marketeers) in the content area:
The DocumentPage rendering is a composite layout which is defined with the following layout:
Note that the layout has a NullLayout selected – this is merely because the Sitecore UI forces us to select a layout before saving the layout on the item. The NullLayout is naturally never rendered.
Just to make the point; in turn, here’s how what the HeaderBlocks composite layout contains:
As you can see, composite layouts uses standard Sitecore UI with no addition, and all I’ve had to do at this point is to create a Composite Layout template and add it to the insert options of the Sublayout Folder template. The template has no fields whatsoever.
So how do you get it to merge the layouts? First you create a class – let’s call it InsertCompositeLayoutRenderings – derive it from Sitecore.Pipelines.RenderLayout.RenderLayoutProcessor and insert it into the renderLayout pipeline in the web.config. The entry needs to be right below the InsertRenderings entry, as this unfolds all the renderings in the current item and fills the Sitecore.Context.Page.Renderings list.
Second, you implement the Process() method of your InsertCompositeLayoutRenderings class, run through the Sitecore.Context.Page.Renderings and detects any composite layouts in the list, parse the layout field in the composite layout item and call Sitecore.Context.Page.AddRendering for each rendering found. If you want recursive support, you merely give the renderings on each composite the same treatment.
Granted, the design has some flaws – e.g. all renderings are added to the end of the layout (theres no InsertRendering method), so you have to be careful about the placeholders you use and order of the composite layouts – but I still consider the solution to be much better than the two options first mentioned.
We could all hope Sitecore reads this post and implements something similar in a future version, but until then if anyone is interested, I’ll consider posting the code on the Sitecore shared source network.