Pages

Thursday, October 14, 2021

Rendering ContentReference Properties

A ContentReference property allows you to select a single ContentData object for reference. By default, when you render these property types with the PropertyFor helper, it renders as a link for a page, or displays the name of a block. This is because the value stored is a ContentReference object, not the ContentData of the item referenced. This is one approach to render that content with a partial view.

Create a DisplayTemplate in your DisplayTemplates folder

At the most basic level this can be handled with a DisplayTemplate that takes a ContentReference for a model, and gets the ContentData for rendering according to the content type. The code below is a DisplayTemplate for a TeaserBlock stored as a ContentReference.

[pre class="brush:razor;class-name:collapse-box" title="_SmallSidebarTeaser.cshtml"]
@using EPiServer
@using EPiServer.Core
@using BaseEpiserverSite.Models.Blocks
@model EPiServer.Core.ContentReference

@{
    var _contentRepository = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IContentRepository>();
    var teaserBlock = _contentRepository.Get<IContent>(Model) as TeaserBlock;

    if (teaserBlock != null)
    {
        <div class="small-teaser">
            <a href="@Url.ContentUrl(teaserBlock.TeaserUrl)">
                <div class="teaser-image">
                    @Html.DisplayFor(x => teaserBlock.TeaserImage, new { Tag = "ContentReferenceImage" })
                </div>
                <div class="teaser-description">
                    @Html.DisplayFor(x => teaserBlock.TeaserDescription)
                </div>
            </a>
        </div>
    }
}
[/pre]

 

Also note that in this sample, I have a DisplayTemplate used just for images that I reference named ContentReferenceImage.

Call the DisplayTemplate using a Tag with PropertyFor for the property.

My HomePage model contains a ContentReference property named SidebarFeaturedItem. By passing the name of my DisplayTemplate as a Tag on the PropertyFor helper, I can use that DisplayTemplate to render this property.

[pre class="brush:razor;class-name:collapse-box"]
<div class="sidebar-content">
    <h4>This is my sidebar</h4>
    @Html.PropertyFor(m => m.CurrentPage.SidebarFeaturedItem, new { Tag = "_SmallTeaserTesting"})
    <p>Test content under the Sidebar Teaser</p>
</div>
[/pre]

 

If using this approach, make sure you restrict the types for your property to the type you create the DisplayTemplate to handle. If you start trying to introduce logic to handle multiple types it's better to use a different method for rendering the items. Also, rendering ContentReference properties this way can generate a mess of DisplayTemplates since you can't reuse a template designed for a specific content type. However, if you do have a partial created for a type already you can use the RenderPartial helper and pass the type.

[pre class="brush:razor;class-name:collapse-box"]
@using EPiServer
@using EPiServer.Core
@using BaseEpiserverSite.Models.Blocks
@model EPiServer.Core.ContentReference

@{
    var _contentRepository = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IContentRepository>();
    var teaserBlock = _contentRepository.Get<IContent>(Model) as TeaserBlock;

    if (teaserBlock != null)
    {
       Html.RenderPartial("_SidebarTeaser", teaserBlock);
    }
}
[/pre]

 

I'll explore additional ways of rendering ContentReference types in upcoming articles.

No comments:

Post a Comment

Share your thoughts or ask questions...