Posted 8/25/2011 by techphoria414
Sitecore is undoubtedly putting increased effort and attention on the Page Editor as both an editing and design tool. This is evident in features such as the Unified Page Editor, layout deltas, and parameters templates. Sitecore 6.4 makes it very easy for a content editor to add a rendering to a placeholder, and even select or create a data source item for it.
However, a recent SDN post brought to light a limitation of the Sitecore layout engine that can make it difficult to build complex pages using placeholders and renderings. The poster posed a reasonable-sounding request, with a frustrating reality:
Sublayout A, has placeholder X.
Sublayout B, has placeholder Y.
Sublayout C, has no placeholder.
Within X on A, I want to place two instances of sublayout B. They are at the same level as each other, we'll call these B1 and B2. However I now want to put C into B2/Y. This can't be done however as the fully-qualified reference for B1/Y and B2/Y is the same, it will just go into B1/Y.
Just today, I had this very situation come up with one of our Information Architects -- how to construct an Accordion Sublayout, with multiple accordion folds, where each of which could contain their own unique content? This could perhaps be done through content heirarchy, perhaps using Presentation Inversion of Control to give some flexibility to the renderings inside the folds. But this is a Content Editor centric approach. Other folks on the thread above did suggest creating additional sublayouts with different placeholder names, but this is a hack and not intuitive to end users.
I don't believe there is a perfect solution currently, and I wouldn't be surprised if Sitecore is working the problem. In the mean time though, I've thrown together a quick prototype of a "wrapper" control for the Placeholder control that gives it a dynamic key. The basic idea:
- Every rendering reference (a rendering assigned to a placeholder in Presentation Details) has a unique ID, though it's not displayed anywhere outside the layout XML.
- Append that unique ID to keys of placeholders within the referenced Sublayout. This provides a unique value for the placeholder key that should remain constant. (As you can see in the code, obtaining that ID at the time Sitecore is constructing the page structure is a bit difficult.)
- Supplement the getPlaceholderRenderings pipeline to treat the placeholder as if it didn't have a GUID appended to it, when looking for placeholder settings.
- Utilize the Page Editor to construct pages -- you will not be able to easily construct pages using dynamic placeholder keys otherwise.
Download the prototype code
UPDATE: There is an updated version of this prototype (which works with Sitecore 6.5) available as part of my Page Editor: Unleashed webinar post.
To try out the supplied code, you'll need to
- Add and compile to your own assembly
- Add GetDynamicKeyAllowedRenderings to the getPlaceholderRenderings pipeline
- Add the namespace of the DynamicKeyPlaceholder class to system.web/pages/controls with a tag prefix of your choice
- Utilize the DynamicKeyPlaceholder class in place of Placeholder in your sublayout, e.g. <xx:DynamicKeyPlaceholder Key="content" />
- Setup your placeholder settings, fire up the Page Editor, and try it out...
A limitation remains that you cannot nest a Sublayout within itself. There is deeper code in Sitecore that prevents this. And sorry kids, can't help you with XSLT renderings here.
Let me reiterate that this is indeed prototype code. No guarantees, warantees, support or in-flight movie provided. But I'm very interested in feedback and other ideas. To keep the conversation going, please comment in the existing SDN thread.
Nick / @techphoria414