Thursday, May 29, 2014

Understand & Customize Display Templates


Display templates are new in sharepoint 2013 replacing XSLT in 2010 which will be used to customize the UI/display of the webparts. Like, we had item.xsl and control.xsl back then, its same strategy in 2013 as well. Entire UI code for a webpart is split into 2 different files, Control and item template. Control template will have the markup that creates the base look/container/header section for the webpart where as item template will  have the markup defined for each result/item displayed.

For every display template(item/control) file(.html) uploaded to the master page gallery, a respective js file will be generated if no syntax errors found. Publishing features at site collection need to be activated so sharepoint could generate those files.

To start with creating a custom item template, copy any of the OOTB template and start following its pattern and conventions. I have explained few notations to make it easy for you and myself.

Ensure all the changes are written inside the first div under the body of the template. Sharepoint reads only the markup which is inside the first div(excluding div element itself) while applying the item template to each item in the webpart.
I have copied part of the code from item_picture3lines.html for better explanation. Here, the first div is  with id=item_picture3lines. Id of the div can be changed but not the div element itself.


<body>
<div id="Item_Picture3Lines" >
<!--#_
var encodedId = $htmlEncode(ctx.ClientControl.get_nextUniqueId() + "_picture3Lines_");
var linkURL = $getItemValue(ctx, "Link URL");
linkURL.overrideValueRenderer($urlHtmlEncode);
...
...
 _#-->

<div class="cbs-picture3LinesContainer" style="font-size:11px;" id="_#= containerId =#_" data-displaytemplate="_#= $htmlEncode(dataDisplayTemplateTitle) =#_">
...

</div>
</div> </body>

Scripting
Javascript/jquery can be written by wrapping it with <!--#_    _#--> without explicit script tags. So it's going to look like,

<!--#_
Var temp;
alert("calling script from display template");
 _#-->

External js file can be included by using the function,includeScript. First parameter is always this.url

$includeScript(this.url, "~sitecollection/_layouts/15/reputation.js");

Similarly external CSS can be referenced using $includeCSS(this.url, "~sitecollection/site library/custom.css");
Read here on how to run the scripts after display template or complete DOM  render($(document).ready())


Property Mappings

To add new lines  in content search webpart or do property/managed metadata mapping in display template,
look for mso:managedPropertyMapping in item template which is responsible for mapping the columns to the variables in the display template and to show in the toolpart.

<mso:ManagedPropertyMapping msdt:dt="string">'Link URL'{Link URL}:'Path','Line 1'{Line 1}:'Title','Line 2'{Line 2}:'Author','Line 3'{Line 3}:'ModifiedOWSDATE','FileExtension'</mso:ManagedPropertyMapping>

'Link URL'{Link URL}:'Path' defines single mapping for a managed metadata.
'Link URL'{Link URL}:'Path'  - first token represents the label of the property displayed in the toolpart under property mappings

'Link URL'{Link URL}:'Path' - second token represents the display name of the variable reference to the actual managed metadata property. This variable will be used in the display template to access the value.

'Link URL'{Link URL}:'Path'  - last token is the actual name of the managed metadata that is used in display template. This is not the display name of the column but the name of the managed metadata property mapped to the crawled property in search schema.

In case of mapping multiple metadata properties to a single display template property variable, follow the below syntax
'Link URL'{Link URL}:'Path;Url'

When no mapping required but need to access the value of managed metadata inside display template just add it in single quotes separated by comma like FileExtension is added.

Context

Sharepoint by default loads the context(ctx) as part of display template that can be used to access many of the contextual properties when customizing display templates.
Access the value of a mapped property by using getitemValue.

Var value = $getItemValue(ctx, "Line 2");

$getItemValue takes the display name of the property(second token in parenthesis) as the second parameter. This way code is generic and it still works even if the property mapping is changed in webpart configuration. Also, if there are managed metadata properties that need to be used(like listItemID,ItemID) that don’t need to be listed in the property mappings, the value of it can be fetched by directly passing the manage metadata property name as per search schema.
The above line of code fetches Author value as {Line 2} is mapped to Author in the display template. Below code also fetches the same value,

Var authorVal  = $getItemValue(ctx, "Author");

Few contextual properties which can be fetched from context,

ctx.CurrentItem.ListItemID
ctx.CurrentItem.SPSiteUrl

To retrieve the current item index  or current row number use the property CurrentItemIdx from ctx  object.

Var currentItemIndex  = ctx.CurrentItemIdx;

Get the row count or total number of rows with,

Ctx.CurrentGroup.RowCount

Row count can be used in the logic when to apply alternate css/styles to the rows, where as row id to display any header section(table header)  for the entire webpart. Header section can be added to control display template but if you don’t want to change 2 different files, just check for currentitemidx=1 and add header section markup in the item template itself.  Note that these properties wont work in control display template.

To find if the results are empty inside control display template,  I checked for DOM length being empty for div.ms-srch-result-noResults.  Thought of using if (ctx.ClientControl.get_shouldShowNoResultMessage()) but did not work as expected. Yet to find a better approach.

Get the unique id by using ctx.ClientControl.get_nextUniqueId();

Access values in markup

Display value of the managed metadata property or a variable as part of the markup. Here authorVal is the variable in the above script having the value of the managed metadata property, Author.

<span>_#= authorVal =#_</span>

1 comment:

  1. Hi MJ! I am able to retrieve the Item Title, Last Modified Date, but Author is eluding me. I have followed your example, but nothing is displayed in the page for who created the item. Do you have any suggestions?

    ReplyDelete