Custom ContentArea without wrapper tags

The default ContentArea rendering will generate something similar to:

<div>
    <div>yourBlockMarkup1</div>
    <div>yourBlockMarkup2</div>
    ...
</div>

This is completly fine in most cases, but sometimes you have markup that you need total control of rendering.

No wrapping tags

I had such a situation. I used it for a slider, where you can put Blocks of different types (representing different type of slides).

/// <summary>
/// Renders blocks without wrapping (div) tags.
/// </summary>
public class NoWrappersContentAreaRenderer
{
    private readonly IContentRenderer _contentRenderer;
    private readonly TemplateResolver _templateResolver;
    private readonly ContentRequestContext _contentRequestContext;

    public NoWrappersContentAreaRenderer(IContentRenderer contentRenderer, 
        TemplateResolver templateResolver,
        ContentRequestContext contentRequestContext)
    {
        _contentRenderer = contentRenderer;
        _templateResolver = templateResolver;
        _contentRequestContext = contentRequestContext;
    }

    public virtual void Render(HtmlHelper helper, ContentArea contentArea)
    {
        var contents = (_contentRequestContext.IsInEditMode(helper.ViewContext.HttpContext)
                            ? contentArea.Contents
                            : contentArea.FilteredContents).ToArray();

        foreach (var content in contents)
        {
            var templateModel = _templateResolver.Resolve(helper.ViewContext.HttpContext, 
                content.GetOriginalType(), content,
                TemplateTypeCategories.MvcPartial, null);

            using (new ContentAreaContext(helper.ViewContext.RequestContext, content.ContentLink))
            {
                helper.RenderContentData(content, true, templateModel, _contentRenderer);
            }
        }
    }
}

Above code generates only the blocks without wrappings tags:

yourBlockMarkup1
yourBlockMarkup2
...

Don’t forget to register view for your Block. Does not require any extra BlockController.

// \Business\Rendering\TemplateCoordinator.cs

viewTemplateModelRegistrator.Add(typeof(RoyalSliderItemBlock), new TemplateModel
{
    Name = "RoyalSliderItemBlock",
    AvailableWithoutTag = true,
    Path = BlockPath("RoyalSliderItemBlock.cshtml")
});

Define a tag

public static class Tags
{
    public const string NoWrappersContentArea = "NoWrappersContentArea";
}

Based on this tag choose a rendering method
/Views/Shared/DisplayTemplates/ContentArea.cshtml:

@model EPiServer.Core.ContentArea

@if (Model != null)
{
    var tag = Html.ViewContext.ViewData["tag"] as string;
    switch (tag)
    {
        case Tags.NoWrappersContentArea:
            Html.RenderNoWrappersContentArea(Model);
            break;
        default:
            Html.RenderContentArea(Model);
            break;
    }
}

Which is defined here
/Extensions/HtmlHelperExtensions.cs:

public static void RenderNoWrappersContentArea(this HtmlHelper helper, ContentArea contentArea)
{
    var renderer = ServiceLocator.Current.GetInstance<NoWrappersContentAreaRenderer>();
    renderer.Render(helper, contentArea);
}

Outputting ContentArea using defined tag

<div id="huge-slider" class="royalSlider rsHuge" style="height: 540px;">
    @Html.PropertyFor(m => m.CurrentPage.RoyalSliderItems, new
        {
            Tag = Tags.NoWrappersContentArea,
        })
</div>

Cumbersome, but works

I was once trying to avoid this 3 steps rendering (taken from Alloy Templates) but I failed and have to revert everything. It was not so obvious at the first look that ContentArea can be very often null and this check in ContentArea.cshtml is very important. (I don’t remember exactly but I will not try again.)

Side note

When I first created this custom renderer I named it after the ContentArea that was making use of it and it was TechnicalDetailsContentAreaRenderer. Later I realized that this particular use case is not so important and the behaviour of this class is more general so I coined a name NoWrappersContentAreaRenderer.

Update:

Source code clarification

All this stuff is based on Alloy Templates (missing class can be found there).

Reklamy
Ten wpis został opublikowany w kategorii EpiServer i oznaczony tagami , , . Dodaj zakładkę do bezpośredniego odnośnika.

2 odpowiedzi na „Custom ContentArea without wrapper tags

  1. Wirusiux pisze:

    Good article, i really need that functionality now. However can’t find this class: ContentRequestContext. Could you please add source code for all project or where to get this class?

Możliwość komentowania jest wyłączona.