How to extend placeholders in Sitecore MVC

Wow it has been ages since I last wrote a blog post so it is about time that I get started again.

A colleague of mine asked me a question the other day about how I would implement a page(experience)-editable accordion spot where each element in the accordion is a rendering item. Kind of like shown below where the content in each accordion element is a rendering with its own datasource. You should be able to personalize and test each rendering individually.

accordion_example

There is a lot of solutions to achieve this but to keep it close to the Sitecore API and to make it work in the Experience Editor I thought how about implementing an accordion placeholder? That is a placeholder that automatically wraps each rendering within it, in <li> elements within an outer <ul> element.

Back in the webforms days this would have been tricky to do but now with the MVC API it is really easy. No control tree that has to be built up, just a glorified text writer.

First we reflect our way into the placeholder extension method that renders out a normal Sitecore placeholder.

This code simply calls the mvc.renderPlaceholder pipeline. Then if we take a closer look at the last processor in this pipeline called Sitecore.Mvc.Pipelines.Response.RenderPlaceholder.PerformRendering

As you can see this processor simply iterates over the renderings placed in the placeholder and render them by calling the renderRendering pipeline.

The really cheap and dirty solution would be simply to override this processor and given some condition (placeholder name starts with accordion) throw in a <ul> and <li> tags around each rendering and job’s done.

I prefer pragmatism and clean code over cheap and dirty so I would like to take the concept a bit further just for fun.

Making it prettier

The RenderPlaceholderArgs inherit from good old PipelineArgs that has a customdata dictionary so we have a way of passing data to the pipeline.

First we create a simple interface called IRenderPlaceholder that has a method Render.

Then we override the PerformRendering processor and implement a check if the custom data dictionary contains a key for a specific placeholder renderer and then we use ReflectionUtil to look up this type and try to cast it to our IRenderPlaceholder interface.

Finally we patch our new processor into the renderPlaceholder pipeline instead of Sitecore.Mvc.Pipelines.Response.RenderPlaceholder.PerformRendering

Note: Ensure that this patch is read in last. Either by placing the include config file in a folder beneath /App_Config/Include or by prefixing the filename with zzz.

Next up we create our AccordionPlaceholderRenderer that implements our IRenderPlaceholder:

Then we write a new html helper extension method that renders out an accordion placeholder by adding the typename to the custom data dictionary.

And voila, all rendering items that are placed within this placeholder now renders out in a list :)

accordion_spot

 

Tips, I’ve received some feedback with some handy tips for the accordion placeholder.

  1. Turn off the accordion Javascript in page edit mode so it is always fully expanded. We typically put a class on body indicating if the page is in page edit mode.
  2. When in page edit mode add some margin to the ul and li elements so these can be clicked in the experience editor. Otherwise you’ll need to navigate up the hierarchy by clicking an inner element and using the navigation on the floating toolbar

 

A little bit of bonus..

Now you can also easily make an extended placeholder that wraps all it’s rendering items in let’s say  a <section> element:

Or a placeholder that only render out 3 renderings at random when not in page edit mode:

And so on and so forth. Just make a new HtmlHelper extension method for each type or implement a generic method where the type is IRenderPlaceholder.

That was it, I hope to blog some more the coming weeks, I’ve been missing it.

 

Anders Laub

Anders Laub Christoffersen

Anders has been working with Sitecore for over a decade and has in this time been the lead developer and architect on several large scale enterprise solutions all around the world. Anders has been nominated a Sitecore Technical MVP three years in a row for 2014, 2015 and 2016. Anders is now working as a Sr. Solutions Architect at Sitecore in Copenhagen.

2 thoughts on “How to extend placeholders in Sitecore MVC

  1. Couldn’t you just use the Item Renderer feature of Sitecore?

    So our approach to this problem would be to create an Accordion Module that allows you to pick a datasource. This datasource would point to a folder of Sitecore Items or you could select from a multilist or whatever. Each of those items they have their own presentation defined in Presentation Details. So our Accordion Module view would just iterate through all of the children in the referenced datasource and call the ItemRendering() command (we are using Glass). This triggers each of the Items referenced views to render our markup.

    Just curious if we are missing a key piece of functionality that your way provides?

    Thanks

    • Hi Jerami, thanks for your comment.

      Your approach is also a fine solution for creating an accordion, I’ve used it as well, and back in the webforms days a similar approach.

      The main difference between reading the presentation details from another item and extending the placeholder as I show in this post is Experience Editor support.

      By using an extended placeholder you will get all the well-known out-of-the-box functionality for personalization and testing on each of the elements in the accordion and not just on the rendering that iterates over its datasource child items and render these.

      Makes sense? Perhaps the “bonus” examples that I show in the end of the post better illustrates the potential of the approach than an accordion.

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*
Website