Render properties with Tag Helpers
Tag Helpers were introduced in ASP.NET Core as an alternative to HTML helpers for rendering HTML in Razor views. Optimizely Content Management System (CMS) version12 did not initially include support for tag helpers since initial release. Tag helpers are a popular alternative for developers, especially when implementing a new site based on CMS 12.
Developers can build coupled sites using Razor views with tag helpers and CMS content. Tag helpers helps us:
- Reduce amount of developer training required to build sites on our CMS.
- Help customers get maximum value from improvements to .NET from MS
- Moving rendering decisions closer to the HTML canvas and making it easier for frontend engineers to take control over the markup/output in the frontend.
- Easier to customize the output.
- Keep the code clean and more intuitive.
- Work with OPE by default
Developers can specify a page model using standard .NET API and get type-aware Intellisense for CMS pages when working with attribute helpers.
Supported property attribute tag helpers
epi-property
– Render content property from the model as inner HTML or attributes depending on the element it's added to.epi-property-item
– Render an element for each child object in a collection (currently only supported for content area item).epi-on-item-rendered
– Specify the method name which will be executed after the html output of content are item has been written.epi-template-tag
– Specify which tag should be applied when resolving the actual template.required-client-resources
– Render client resources by using tag helpers.
Tag helpers support the same number of HTML elements and generate the same HTML output as the Html.PropertyFor
does. Tag helpers should supported built-in properties:
CategoryList
ContentArea
ContentData
ContentReferenceList
ContentReference
LinkItemCollection
LinkItem
Url
XhtmlString
DateTime
Int
Double
Boolean
String
LongString
Weekday
The following steps show how to use this feature:
-
Install the
EPiServer.CMS.AspNetCore.TagHelpers
package. -
Create a content type like following
[ContentType] public class MyPage : PageData { public virtual CategoryList CategoryList { get; set; } public virtual ContentArea ContentArea { get; set; } public virtual IList<ContentReference> ContentReferenceList { get; set; } public virtual ContentReference ContentReference { get; set; } public virtual ContentReference TargetPage { get; set; } [UIHint(UIHint.Image)] public virtual ContentReference Image { get; set; } public virtual PageReference PageReference { get; set; } public virtual LinkItem LinkItem { get; set; } public virtual LinkItemCollection LinkItemCollection { get; set; } public virtual Url Url { get; set; } public virtual XhtmlString XhtmlString { get; set; } // other properties }
-
Specify model in view: ~/Views/MyPage/Index.cshtml
@model MyPage
-
Register dependencies in Startup.cs.
services.AddCmsTagHelpers();
-
To make the tag helpers available to all our Razor views, add the
addTagHelper
directive to the Views/_ViewImports.cshtml file:@addTagHelper *, EPiServer.Cms.AspNetCore.TagHelpers
NOTE
The following examples should work with OPE by default.
Category list examples
<span epi-property="CategoryList" />
HTML output in view mode:
<span>Category1,Category2</span>
ContentReference examples
With anchor (<a>) tag:
<a epi-property="ContentReference" />
HTML output in view mode
when target content is a page or routable content
<a href="/en/mytargetcontent/">My target content name</a>
when target content is non-routable content
<a>My target content name</a>
You could specify value for attributes
<a epi-property="ContentReference" href="https://custom.domain.com" data-custom-attribute="something" />
HTML output in view mode:
<a href="https://custom.domain.com" data-custom-attribute="something">My target content name</a>
You could provide custom text
<a epi-property="ContentReference" href="https://custom.domain.com" data-custom-attribute="something">Custom text</a>
HTML output in view mode:
<a href="https://custom.domain.com" data-custom-attribute="something">Custom text</a>
With non-anchor (<a>) tag:
<span epi-property="ContentReference" />
<p epi-property="ContentReference" />
Output in view mode:
<span>My target content name</span>
<p>My target content name</p>
With <img> tag:
<img epi-property="ContentReference" />
Output in view mode:
when target content is an image
<img src="/globalassets/image.jpg" />
when target content is non-routable content
<img />
You could combine anchor (<a>) tag and <img> tag
<a epi-property="TargetPage" class='awesome'>
<img epi-property="Image" class="image" alt="My Image" />
</a>
HTML output in view mode:
<a href="/en/target-page/" class='awesome'>
<img src="/globalassets/image.jpg" class="image" alt="My Image" />
</a>
PageReference examples
With anchor (<a>) tag:
<a epi-property="PageReference" />
HTML output in view mode:
<a href="/en/target-page/">My target page name</a>
With non-anchor (<a>) tag:
<span epi-property="PageReference" />
<p epi-property="PageReference" />
Output in view mode:
<span>My target page name</span>
<p>My target page name</p>
ContentReference list examples
With <ul> tag
<ul class="content-links" epi-property="ContentReferenceList" />
Example HTML output in view mode:
<ul class="content-links">
<li>
<a href="/en/alloy-track/" target="_blank" title="Link title">Link text</a>
</li>
<li>
<a href="/globalassets/image.jpg" target="_blank" title="Image title">Image text</a>
</li>
</ul>
The same with <ol> tag
<ol epi-property="ContentReferenceList" type="A" class="awesome-list" />
Example HTML output in view mode:
<ol type="A" class="awesome-list">
<li>
<a href="/en/alloy-track/" target="_blank" title="Link title">Link text</a>
</li>
<li>
<a href="/globalassets/image.jpg" target="_blank" title="Image title">Image text</a>
</li>
</ol>
NOTE
Only HTML list ul and ol are supported. If other HTML tags are used, the output will look something like:
<div class="awesome" epi-property="ContentReferenceList" />
<div class="awesome">
<a href="/en/alloy-track/">Alloy Track</a>
<a href="/globalassets/image.jpg">Awesome image</a>
</div>
LinkItem examples
NOTE
The HTML attribute target and title and link text are rendered based on values that is set in OPE. If the attributes and/or custom text is provided, those values would be used to render.
When link item refers to a page
<a epi-property="LinkItem" />
Output in view mode:
<a href="/en/alloy-plan/" target="_blank" title="Alloy Plan">Alloy Plan</a>
You could provide custom value for attributes
<a epi-property="LinkItem" href="https://custom-link.com" title="Custom title" target="_parent"/>
Output in view mode:
<a href="https://custom-link.com" title="Custom title" target="_parent">Alloy Plan</a>
You could provide custom text
<a epi-property="LinkItem" class="custom-class" title="Custom Title">Custom text</a>
HTML output in view mode:
<a href="/en/alloy-plan/" class="custom-class" title="Custom Title">Custom text</a>
When link item refers to an image
<img epi-property="LinkItem" />
Output in view mode:
<img src="/globalassets/image.jpg" title="My image" />
You could also specify values for attributes
<img epi-property="LinkItem" src="https://custom-src.com" class="custom-class" title="Custom Title"/>
HTML output in view mode:
<img src="https://custom-src.com" class="custom-class" title="Custom Title"/>
LinkItemCollection examples
With <ul> tag
<ul epi-property="LinkItemCollection" class="awesome-list" />
Example HTML output in view mode:
<ul class="awesome-list">
<li>
<a href="/en/alloy-track/" target="_blank" title="Link title">Link text</a>
</li>
<li>
<a href="/globalassets/image.jpg" target="_blank" title="Image title">Image text</a>
</li>
</ul>
The same with <ol> tag
<ol epi-property="LinkItemCollection" type="A" class="awesome-list" />
Example HTML output in view mode:
<ol type="A" class="awesome-list">
<li>
<a href="/en/alloy-track/" target="_blank" title="Link title">Link text</a>
</li>
<li>
<a href="/globalassets/image.jpg" target="_blank" title="Image title">Image text</a>
</li>
</ol>
NOTE
Only HTML list <ul> and <ol> are supported. If other HTML tags are used, the output will look something like:
<div class='awesome' epi-property="LinkItemCollection" />
<div class="awesome">
<a href="/en/alloy-track/" target="_blank" title="Link title">Link text</a>
<a href="/globalassets/image.jpg" target="_blank" title="Image title">Image text</a>
</div
URL examples
When URL refers to a page
<a epi-property="Url" class="awesome" />
HTML output in view mode:
<a href="/en/alloy-plan/" class="awesome">Alloy Plan</a>
When URL refers to an image
<img epi-property="Url" class="awesome" title='Awesome image' />
HTML output in view mode:
<img src="/globalassets/image.jpg" class="awesome" title="Awesome image" />
XhtmlString examples
The same for XhtmlString
, it could be rendered by writing
<div id="xhtmlString" class="awesome" epi-property="XhtmlString" />
The HTML output will be rendered based on string fragments that the XhtmlString
consists of.
<div id="xhtmlString" class="awesome">
<!-- Content of fragments -->
</div>
Block examples
You can specify template tag when rendering block
<div id='TeaserBlock' class="awesome" epi-property="TeaserBlock" epi-template-tag="wide" />
HTML output:
<div id='TeaserBlock' class="awesome">
<!-- Content of block template -->
</div>
ContentArea example
HTML markup
<div epi-property="ContentArea" epi-template-tag="fullWidth" />
HTML output:
<div>
<div>{{ContentAreaItem1_PlaceHolder}}</div>
<div>{{ContentAreaItem2_PlaceHolder}}</div>
</div>
Custom template for content area item with epi-property-item attribute
<div class="awesome"
epi-property="ContentArea"
epi-template-tag="wide">
<p epi-property-item class="awesome" data-attribute="@attributes" />
</div>
HTML output:
<div class="awesome">
<p class="awesome" data-attribute="@attributes">
{{ContentAreaItem1_PlaceHolder}}
</p>
<p class="awesome" data-attribute="@attributes">
{{ContentAreaItem2_PlaceHolder}}
</p>
</div>
The template can also be nested multiple levels
<div class="awesome"
epi-property="ContentArea"
epi-template-tag="wide">
<div class="children-class">
<p class="grand-children-class">
<a epi-property-item class="content-area-item" />
</p>
</div>
</div>
HTML output:
<div class="awesome">
<div class="children-class">
<p class="grand-children-class">
<a class="content-area-item">
{{ContentAreaItem1_PlaceHolder}}
</a>
</p>
</div>
<div class="children-class">
<p class="grand-children-class">
<a class="content-area-item">
{{ContentAreaItem2_PlaceHolder}}
</a>
</p>
</div>
</div>
Use extension method to customize the rendering process of content area item. Define a function in view like the following:
@functions
{
public void OnItemRendered(ContentAreaItem contentAreaItem, TagHelperContext context, TagHelperOutput output)
{
output.AddClass("customize-item", System.Text.Encodings.Web.HtmlEncoder.Default);
}
}
And pass the function name as value to epi-on-item-rendered attribute when rendering
<div class='content-area' epi-property="ContentArea">
<p epi-property-item class="content-area-item" epi-on-item-rendered="OnItemRendered" />
</div>
Example HTML output:
<div class="content-area">
<p class="content-area-item customize-item">{{ContentAreaItem1_PlaceHolder}}</p>
<p class="content-area-item customize-item">{{ContentAreaItem2_PlaceHolder}}</p>
</div>
Render client resources example
You can render client resources by using Tag Helpers:
<required-client-resources area="Header" />
This is the same as @Html.RequiredClientResources("Header")
. The default valid areas are Header and Footer.
Updated 4 months ago