Enable dynamic MVC content place holders for Sitecore – Part 1

Background

In one of my projects I have the requirement to allow the content administrator to create content using a large set of pre-defined content blocks (renderings). The provided design required the responsive website to wrap content rows into div tags. For this project we had to allow the content administrator to mix and match content blocks for 1 colomn, 2 column and 3 column layouts on the same page. Here’s an example of how a sample page could look like:

CompositePage

This is a simplified view of the various different content blocks. Also the number of required rows and columns vastly wary from page to page.

Since the numbers of rows would not be known at the time of creating the Sitecore layout view, only the ‘Header’, ‘Menu’ and ‘Main’ place holders could be defined in the mark-up. Each of the content rows rendered in the main content place holder would be wrapped in a row rendering that contains a place holder used to render content blocks.

In Sitecore it does not make sense to declare a content place holder with the same name more than once on a particular page. If you were trying to do that, Sitecore would render everything in the first occurrence of the place holder and ignore the others.

In order to overcome this limitation I realised that I had to find a way to declare content place holders on the fly from the content authoring environment. The following stackoverflow article describes how to do that but I didn’t like that it uses a Guid as the dynamic part of the name. Hence I decided to blog how I overcame that limitation allowing to declare more meaningful dynamic place holder names.

Let’s get started with code

Layout view

@using Sitecore.Mvc
<!DOCTYPE html>
<html lang="en" dir="ltr" class="no-js">
 <head>
 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
 </head>
<body>
 @Html.Sitecore().Placeholder("main")
</body>
</html>

The other content place holders such as navigation and header have been left out since they are not relevant for this example.

Row rendering

@using HelveticSolutions.Web.Sitecore.Mvc
@using Sitecore.Mvc
<div class="row">
 @Html.Sitecore().DynamicPlaceholder("row")
</div>

DynamicPlaceholder extension

This is the extension method that renders an actual content place holder with a unique name:

namespace HelveticSolutions.Web.Sitecore.Mvc
{
 using System.Web;

 using global::Sitecore.Mvc.Helpers;

 using global::Sitecore.Mvc.Presentation;

 public static class SitecoreHelperExtensions
 {
 #region Public Methods and Operators

 public static HtmlString DynamicPlaceholder(this SitecoreHelper helper, string placeholderNamePrefix)
 {
   string rowNumberParameter = RenderingContext.Current.Rendering.Parameters["Row"];
   string placeholderNameSuffix = !string.IsNullOrWhiteSpace(rowNumberParameter) ?
       rowNumberParameter :
       RenderingContext.Current.Rendering.UniqueId.ToString();
   string placeholderName = string.Concat(placeholderNamePrefix, "__", placeholderNameSuffix);
   return helper.Placeholder(placeholderName);
 }

 #endregion
 }
}

The dynamic place holder name is concatenated using

  1. The prefix passed in via the DynamicPlaceholder extension method call, in our sample ‘row’
  2. A separator ‘__’
  3. The suffix configured as a rendering parameter with the key ‘Row’ which is optional. In absence of the parameter the suffix will fall back to the renderings unique identifier.

Sample content block rendering (2 columns per row) using Bootstrap

<div class="col-xs-6">
 Lorem ipsum...
</div>

Sitecore configuration

  1. Create a new layout that references your layout view
    MyLayout
  2. Create new view rendering that references your row view
    RowViewRendering
  3. Create new view rendering that references your sample content block view
    SampleBlockViewRendering
  4. Modify presentation of the sample page
    1. Use layout from above
    2. Remove all existing renderings
    3. Add a new row rendering and add a rendering parameter for the row suffix
      RenderingParameter
    4. Add a new sample block rendering and choose the dynamic place holder name as place holder
      DynamicPlaceholderNameInUse
    5. Repeat the last step so that we have two text blocks in the row for our two column layout
  5. Publish

The sample page should look something like this:

DynamicPlaceholderSamplePage

In the second part of this blog post I am going to show how dynamic place holders with meaningful names can be enabled in the page editor.

One Reply to “Enable dynamic MVC content place holders for Sitecore – Part 1”

Leave a Reply

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