Re-use block for two different renderings

Vote:
 

Block type: ContentBlock

Default controller:

[TemplateDescriptor(
    AvailableWithoutTag = true,
    Default = true,
    Tags = new []
{
    Constants.ContentAreaTags.Column1,
    Constants.ContentAreaTags.Column2,
    Constants.ContentAreaTags.Column3,
    Constants.ContentAreaTags.Column4,
    Constants.ContentAreaTags.Column5,
    Constants.ContentAreaTags.Column6,
    Constants.ContentAreaTags.Column7,
    Constants.ContentAreaTags.Column8,
    Constants.ContentAreaTags.Column9,
    Constants.ContentAreaTags.Column10,
    Constants.ContentAreaTags.Column11,
    Constants.ContentAreaTags.Column12
})]
public class ContentBlockController : BlockController
{
    public override ActionResult Index(ContentBlock currentBlock)
    {
        return PartialView("~/Views/Blocks/ContentBlock/Index.cshtml", currentBlock);
    }
}

Controller for rendering a ContentBlock differently:

[TemplateDescriptor(AvailableWithoutTag = false,
    Tags = new[]
{
    "ContentAreaRibbonBlock",
    Constants.ContentAreaTags.Column1,
    Constants.ContentAreaTags.Column2,
    Constants.ContentAreaTags.Column3,
    Constants.ContentAreaTags.Column4,
    Constants.ContentAreaTags.Column5,
    Constants.ContentAreaTags.Column6,
    Constants.ContentAreaTags.Column7,
    Constants.ContentAreaTags.Column8,
    Constants.ContentAreaTags.Column9,
    Constants.ContentAreaTags.Column10,
    Constants.ContentAreaTags.Column11,
    Constants.ContentAreaTags.Column12
})]
public class ContentBlockForRibbonController : BlockController
{
    public override ActionResult Index(ContentBlock currentBlock)
    {
        return PartialView("~/Views/Blocks/ContentBlock/ContentBlockForRibbon.cshtml", currentBlock);
    }
}



Content area that has my special tag to differentiate rendering:

@Html.PropertyFor(x => x.ContentArea, new { Tag = "ContentAreaRibbonBlock", HasContainer = true, CssClass = "row", ChildrenCssClass = "dynamic-box" })

The Constants.ContentAreaTags properties are also used as DisplayOptions from within Episerver edit mode.

When I insert a ContentBlock in this area you see above without applying a DisplayMode, it renders fine. But when I apply a DisplayOptions, ex. Column4 = "col-sm-4", it's rendered by my Default controller.

How is that possible? My ContentBlockForRibbonController has tags values that are more specific than ContentBlockController...

#149860
Jun 09, 2016 9:22
Vote:
 

Only the display option will actually be passed along as tag in your case. That means that your default controller will be used since it's marked as default (both controllers support the tag). The tag you specify in 

@Html.PropertyFor(x => x.ContentArea, new { Tag = "ContentAreaRibbonBlock", HasContainer = true, CssClass = "row", ChildrenCssClass = "dynamic-box" })

will be ignored. 

Inherit EPiServer.Web.Mvc.Html.ContentAreaRenderer and change the method for GetContentAreaItemTemplateTag to change this behaviour if needed. 

#149864
Edited, Jun 09, 2016 10:24
Vote:
 

Hi Daniel,

That is done now. But I've been trying to figure out how I can spot it the current ContentAreaItem was inserted in a content area with my "ContentAreaRibbonBlock" tag?

Got any ideas?

Thanks!

#149874
Jun 09, 2016 13:40
Vote:
 

If you inherit ContentAreaRenderer you can always add logging with ILogger interface to see what is coming in...

#149875
Jun 09, 2016 13:43
Vote:
 

The final solution to my issue was to override ContentAreaRenderer, and override its method 'GetContentAreaItemTemplateTag', as Daniel said.

But here's the code I ended up with:

protected override string GetContentAreaItemTemplateTag(HtmlHelper htmlHelper, ContentAreaItem contentAreaItem)
{
    string tag = htmlHelper.ViewContext.ViewData[RenderSettings.Tag] as string;
    DisplayOption displayOption = contentAreaItem.LoadDisplayOption();

    // If no tag was specified in the view, and a display option was set => use that.
    if (tag == null && displayOption != null)
    {
        return displayOption.Tag;
    }

    // If a tag was specified in the view => use that.
    if (tag != null)
    {
        return tag;
    }
            
    // Fallback
    return base.GetContentAreaItemTemplateTag(htmlHelper, contentAreaItem);
}

The comments should explain my code.

Thanks again, Daniel.

#149876
Jun 09, 2016 13:54
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.