Dynamic Placeholder Keys Prototype
Posted 08/25/2011 by techphoria414
I just became aware of an article by MVP Eduardo Moraes that describes a dynamic placeholder approach that allows you to define your own suffix, solving the usability issue of rendering GUIDs, and the deletion and other UX issues created by auto-appending a counter. As he points out, adding a reasonable default to the user-defined rendering ID would make this an even better solution. I think ultimately the Sitecore solution to this (SITECORE PLEASE DO THIS YESTERDAY) will resemble SPEAK, with a user-provided rendering ID prefix, with a default value (e.g. MyRendering1.placeHolderName).
Define the Key for Dynamic Placeholders by Eduardo Moraes
Meanwhile, everyone hop on the Sitecore UserVoice and vote for native support for Dynamic Placeholders now! (Though this UV is for MVC, I think Webforms support is crucial too..)
Dynamic placeholders continue to be one of the most common and necessary extensions to WebEdit ... Page Editor ... I mean Experience Editor-centric Sitecore implementations. Sitecore perhaps has plans to address this -- the SPEAK framework has some of its own unique workarounds in fact. But in the mean time, if you want dynamic placeholders without all the work, Mark Servais and Jamie Stump have created a Marketplace module that works for both MVC and Webforms! Thanks gentlemen.
Integrated Dynamic Placeholders
If you want dynamic placeholders on steroids, check out the BrainJocks SCORE platform. It not only includes their own version of dynamic placeholders, but also rendering transformations, elastic renderings, cascading elements, and other very cool extensions to Sitecore rendering. Pavel Veller, Brian Beckham and team have done some nice work.
Wow, this post continues to be one of the most popular on my blog! Probably because Sitecore still hasn't resolved the issue. We use an updated version of this approach in Active Commerce, and I've used it for other production sites as well. Note that the referenced code is for Webforms on Sitecore 6.5. There are some changes needed for 6.6. I would recommend reviewing the following links as well if you are going to implement dynamic placeholders.
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