How To Configure Episerver To Allow Users To Render Blocks At Different Sizes

In Episerver 7.5 and above, a new feature was released that allows content editors to change the widths of blocks and pages partials. In my last article How To Make A Block Use Multiple Views ? A Partial View Controller Explained I briefly covered this topic, but today, I’m going to dig a bit deeper under the covers and explain how you can enable ‘Display Options’ in your site.

Why Use Display Options?

One of the benefits of allowing content editors to drop a block or a page within a content area is that they have a lot of flexibility over the layout of the page. In the old days, companies were given a template that defined the page and content editors had very little options to change that layout. When the business decided they wanted to move a block from the left hand side to the right hand side it would have usually involve a developer or designer to make the change and redeploy. In some places that could be a two week process.

Since Episerver 7.5 and the additions of blocks and display options, gone are the days of the business being stuck with fixed layouts. This gives a lot more power to the content editors, they can decide what blocks should be displayed on a page, in what order blocks should appear and now the width the block should be as well. With this extra flexibility also comes a lot of complexity, you need to understand responsive grids and it also means our code base gets slightly more complex. Today’s tutorial will guide you to setting this up in your own site.

episerver_display_options_dialog

How Display Options Works

In the editor when a user sets a display option, a tag property is stored against that block or page partial in the database. This tag can later be accessed by a partial controller, controller or template co-ordinator when a content area is being rendered. Based on the value of this tag we can then either call a completely different view for each width, or, you can pass in a parameter to the view and change the outputted CSS to alter the width. For example, assuming you know a bit about responsive grids, you can think of this CSS change as swapping the grid width class from say 12 rows for a full width display option to 6 rows for a half width display option.

Setting It Up

To enable display options you will need to create an Initialization Module, I usaully call mine ‘DisplayRegistryInitialization’ but feel free to rename it as appropriate. In this tutorial,l I am going to register 5 display options for our site but you can add or remove as many as you like. For our site we will have these options:

  • Full Width
  • Two Thirds
  • Half Width
  • One Third
  • One Fourth

Our code will look like this:

[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class DisplayOptionsConfig : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
var options = ServiceLocator.Current.GetInstance<DisplayOptions>();
foreach (var optionId in options.Select(x => x.Id).ToArray())
{
options.Remove(optionId);
}
options
.Add("full", DisplayOptionTags.FullWidth, DisplayOptionEnum.Full.ToString(), string.Empty, "epi-icon__layout--full")
.Add("wide", DisplayOptionTags.TwoThirdsWidth, DisplayOptionEnum.TwoThirds.ToString(), string.Empty, "epi-icon__layout--two-thirds")
.Add("half", DisplayOptionTags.HalfWidth, DisplayOptionEnum.Half.ToString(), string.Empty, "epi-icon__layout--half")
.Add("narrow", DisplayOptionTags.OneThirdWidth, DisplayOptionEnum.OneThird.ToString(), string.Empty, "epi-icon__layout--one-third")
.Add("quarter", DisplayOptionTags.OneFourthWidth, DisplayOptionEnum.OneFourth.ToString(), string.Empty, "epi-icon__layout--one-fourth");
}
public static void RegisterRoutes(RouteCollection routes)
{
}
public void Uninitialize(InitializationEngine context)
{
}
public void Preload(string[] parameters)
{
}
}

The DisplayOptionTags class is defined below. As you can see it maps to Bootstraps grid css.

public static class DisplayOptionTags
{
public const string FullWidth = "Full Width";
public const string TwoThirdsWidth = "Two Thirds Width ";
public const string HalfWidth = "Half Width ";
public const string OneThirdWidth = "One Third Width ";
public const string OneFourthWidth = "One Fourth Width ";
}

How To Render Different Sized Views

Now we have all the code we need to enable display options in Episerver, the next part of the puzzle is using this data in our views to change our partial widths.

I’m going to assume you have a base partial and/or block controller in your project. If you have no idea what I’m talking about then download my free code sample that contains a base controller from this tutorial EPiServer: Dependencies in Episerver Explained .

In our base partial controller we’re going to add a method to return the display option tag.

protected DisplayOptionEnum GetDisplayOptionTag()
{
var renderSettings = this.ControllerContext.RouteData.Values["renderSettings"] as Dictionary<string, object>;
if (renderSettings == null)
return DisplayOptionEnum.Unknown;
object tag;
if (!renderSettings.TryGetValue("tag", out tag))
return DisplayOptionEnum.Unknown;
if (tag == null)
return DisplayOptionEnum.Unknown;
return GetDisplayOptionTag(tag.ToString());
}
public static DisplayOptionEnum GetDisplayOptionTag(string tag)
{
DisplayOptionEnum displayOptionEnum;
Enum.TryParse<DisplayOptionEnum>(tag, out displayOptionEnum);
return displayOptionEnum;
}
public static string GetDisplayOptionsTag(DisplayOptionEnum value)
{
var displayOptionName
= value.GetAttributeOfEnumValue<DisplayOptionNameAttribute>()
.IfNotDefault(x => x.Name);
return displayOptionName;
}

This code also uses below two custom attributes I created:

public class DisplayOptionNameAttribute : Attribute
{
public string Name { get; set; }
}
public class BootstrapClassAttribute : Attribute
{
public string Name { get; set; }
}

The code also uses a custom Enum I’ve created called DisplayOptionEnum. One import thing to note is the BootstrapClassAttribute defined on each property which defines it’s associated bootstrap class. We will use this when we’re rendering our views.

public enum DisplayOptionEnum
{
Unknown,
[BootstrapClass (Name = "col-md-12")]
[DisplayOptionName(Name = DisplayOptionTags.FullWidth)]
Full,
[BootstrapClass (Name = "col-md-8")]
[DisplayOptionName(Name = DisplayOptionTags.TwoThirdsWidth)]
TwoThirds,
[BootstrapClass (Name = "col-md-6")]
[DisplayOptionName(Name = DisplayOptionTags.HalfWidth)]
Half,
[BootstrapClass (Name = "col-md-4")]
[DisplayOptionName(Name = DisplayOptionTags.OneThirdWidth)]
OneThird,
[BootstrapClass (Name = "col-md-3")]
[DisplayOptionName(Name = DisplayOptionTags.OneFourthWidth)]
OneFourth
}

Now, in our partial view controller, we can call GetDisplayOptionTag() from the base class and get the correct display option. I’m using enums as, from previous experience, I’ve found it makes life a lot easier to unit test rather than just working with strings.

Lastly, it uses this extension method:

GetAttributeOfEnumValue is a custom extension method and can be seen here:

public static T GetAttributeOfEnumValue<T>(this object enumVal)
where T : System.Attribute
{
T enumAttribute = null;
var type = enumVal.GetType();
var memInfo = type.GetMember(enumVal.ToString());
if (memInfo == null || !memInfo.Any())
{
return null;
}
var attributes = memInfo.FirstOrDefault().GetCustomAttributes(typeof(T), false);
if (attributes != null)
{
enumAttribute = attributes.EmptyIfNull().Any() ? (T)attributes.FirstOrDefault() : null;
}
return enumAttribute;
}

Displaying The Tag On The Screen

In our front end code I can then call the GetBootstrapClass extension (also defined below) to get the correct CSS class to display.

<div class="@Model.GetBootstrapClass()" >
</div>

Now we need a GetBootstrapClass() in our view model. Depending on how you have set-up your project will determine where this code will go. I personally always use a base view model so I’m going to stick all my code in there:

public class BlockViewModel<T> : IBlockViewModel<T>
where T : BlockData
{
internal IEpiserverDependencies _epiServerDependencies;
public BlockViewModel(T currentBlock, DisplayOptionEnum _displayOptionTag)
{
_epiServerDependencies = epiServerDependencies;
DisplayOptionTag = _displayOptionTag;
if (currentBlock == null)
throw new ArgumentNullException("currentBlock");
CurrentBlock = currentBlock;
}
public T CurrentBlock { get; private set; }
public DisplayOptionEnum DisplayOptionTag { get; set; }
public string GetBootstrapClass()
{
return DisplayOptionTag.GetAttributeOfEnumValue<BootstrapClassAttribute>().IfNotDefault(x => x.Name);
}
}

Setting The Display Option

Then in each of your block controllers you need to pass in the DisplayOptionTag, which is done like this:

public override ActionResult Index(ColourBlock currentBlock)
{
var displayTag = GetDisplayOptionTag();
return PartialView("Index", new ColourBlockViewModel(currentBlock, EpiserverDependencies, displayTag));
}

Conclusion

We’ve gone through quite a lot of code to get here but finally we now have a way to render different sized blocks based on the display options set by the content editors. I’m using Enums a lot as I’ve found it a lot easier to unit test and ensure everything’s working as it should be.

Code Sample

All the above code can be downloaded in a fully working website from my github account here.

EpiserverDisplayOptionsAndPreview

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

More Posts

4 replies
  1. ronald
    ronald says:

    Thanks for the excellent code, but i’m getting stuck on this line:

    DisplayOptionEnumvaluevalue
    in the function ‘GetDisplayOptionTag’

    Is there a typo there?

    Reply
    • jon
      jon says:

      DisplayOptionEnum value; Its the parameter for the out variable, have updated the code, thanks for spotting it 🙂 Any other questions give me a shout

      Reply
  2. Daniel
    Daniel says:

    This is an excellent post! It works, but it doesnt look quite good in editor mode. The divs, blocks, are stacked on top of eachother with 100% width, rather than being displayed in a grid. Any tips?

    Reply
    • jon
      jon says:

      Hi, have you read How to Preview a Block in Episerver . From the top of my head I think you would need to customize either your block preview controller or your block preview html view depending on your requirements. For example if you wanted a different display for a certain block in your preview controller you could check for that type and then return a different view, e.g. preview_ingrid.cshtml

      Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

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