SharePoint 2013 Customize Display Template for Content By Search Web Part (CSWP) Part-1
This blog post will explore basics of customizing SharePoint 2013 Content By Search Web Part (CSWP) using Display Templates. In my next Post "SharePoint 2013 Customize Display Template for Content By Search Web Part (CSWP) Part-2" I will show how to use a JQuery Plugin with Display Templates and customize the look and feel of CSWP.
Content By Search Web Part
Content By Search Web Part(CSWP) was introduced in SharePoint 2013. CSWP has power to display dynamic content from SharePoint search index, based on dynamic search queries. It uses Display Templates for styling and formatting search results on the page. A big advantage of using CSWP over CQWP is, there are no scope boundaries for getting data across sites. However freshness of results depends on the latest crawl on content.
Display Templates
Display Templates are used with CSWP to format/style search result generated by CSWP search query. Display Templates control which managed property is shown in the search results and how they appear in the Web Part. Each Display Template has two files: an HTML version of the Display Template that you can edit in your HTML editor, and a .js file that is for SharePoint use and should never be modified. CSWP uses combination of two Display Templates, Control Templates and Item Templates to render results.
Control Template provides HTML to structure the overall layout for how you want to present the search results. For example, the Control Template might provide the HTML for a heading, beginning and end of a list. The Control Template is rendered only once in the Web Part.
Item Template provides HTML that determines how each item in the result set is displayed. For example, the Item Display Template might provide the HTML for a list item that contains a picture, three lines of text that are mapped to different managed properties associated with the item. The Item Display Template is rendered one time for each item in the result set. So, if the result set contains ten items, the Item Display Template creates its section of HTML ten times.
For more information about Display Templates, see the "Search-driven Web Parts and Display Templates" section in Overview of the SharePoint 2013 page model.
Explore Display Templates
In a SharePoint 2013 Publishing site, map a network drive to master pages gallery. Follow Map a network drive to the SharePoint 2013 Master Page Gallery.
Once your drive is mapped navigate to Display Templates --> Content Web Parts
Under Content Web Parts Library there are several file names starting with "Control_" and "Item_", files starting with Control are Control Templates and files starting with Item are Item templates. Also there are two file extensions for each file type .html and .js.
.js is strictly for SharePoint internal use and not to be changed by users. Throughout the post we will be using .html extension and SharePoint will automatically update .js based on changes we have made to .html.
Now let's open a Control Template and examine some important properties.
Explore Control Display Template
Following code is from one of my Custom Control Template that we will discuss in my next post.
Header Properties
This section has Display Template header properties that provide information to SharePoint about Display Template, <title> will be displayed under CSWP Edit Properties to choose from.
<title>JSlider</title>
<!--[if gte mso 9]><xml> <mso:CustomDocumentProperties> <mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden> <mso:MasterPageDescription msdt:dt="string">This is the default Control Display Template that will list the items. It does not allow the user to page through items.</mso:MasterPageDescription> <mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106601</mso:ContentTypeId> <mso:TargetControlType msdt:dt="string">;#Content Web Parts;#</mso:TargetControlType> <mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated> <mso:HtmlDesignConversionSucceeded msdt:dt="string">True</mso:HtmlDesignConversionSucceeded> <mso:HtmlDesignStatusAndPreview msdt:dt="string">https://demo.contoso.com/sites/Jquery-displaytemplate-demo/_catalogs/masterpage/Display Templates/Content Web Parts/Control_JSlider.html, Conversion successful.</mso:HtmlDesignStatusAndPreview> </mso:CustomDocumentProperties> </xml><![endif]-->
Script Block
This section is used to reference JavaScript and CSS files.
<script>
$includeLanguageScript(this.url,"~sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js");
$includeScript(this.url,"~sitecollection/style library/slider/js/jquery-1.9.1.min.js");
$includeScript(this.url,"~sitecollection/style library/slider/js/jquery.slides.min.js");
$includeCSS(this.url,"~sitecollection/style library/Slider/css/example.css");
<!--$includeCSS(this.url, "~sitecollection/style library/Slider/css/font-awesome.min.css");-->
$includeCSS(this.url,"~sitecollection/style library/Slider/css/charm.css");
</script>
DIV Block
Following the <script> tag is a <div> tag with an ID. By default the ID for this <div> tag matches the name of the Display Template file. The HTML or JavaScript you want the display template to render must be included inside this <div> tag. However, the tag itself is not included in the markup that is rendered on the webpage.
<div id="Control_List">
<!--#_
if (!$isNull(ctx.ClientControl) &&
!$isNull(ctx.ClientControl.shouldRenderControl) &&
!ctx.ClientControl.shouldRenderControl())
{
return "";
}
ctx.ListDataJSONGroupsKey = "ResultTables";
var siteURL = SP.PageContextInfo.get_siteServerRelativeUrl();
_#-->
<div class="container">
<div class="slides">
_#= ctx.RenderGroups(ctx) =#_
<a href="#" class="slidesjs-previous slidesjs-navigation"><i class="icon-chevron-left icon-large"></i></a>
<a href="#" class="slidesjs-next slidesjs-navigation"><i class="icon-chevron-right icon-large"></i></a>
</div>
</div>
<!--#_
AddPostRenderCallback(ctx, function(){
$.getScript(siteURL + "/style library/Slider/js/jquery.slides.min.js", function(){
$('.slides').slidesjs({
width: 940,
height: 528,
navigation: true
});
})
});
_#-->
</div>
Few important points to note here:
Any JavaScript Code should be inside <!--#_ <JavaScript Code> _#-->
Use value assigned to variable using _#= example: <a href ="_#=LinkURL=#_">
In Control Template _#=ctx.RenderGroups(ctx) =#_ is used to render HTML items (actual search results) from Item template.
For CSS styling, wrap _#=ctx.RenderGroups(ctx) =#_ with a div and apply css style, this will style all items coming from Item Template. Point to note here is, most outer <div>with ID matching template title will never render in HTML, so be careful not to apply style to outer <div>or it will never reflect.
To call a JavaScript function after Display Template is completely rendered use the AddPostRenderCallback function. I will use this function to call a JQuery Plugin in my next post.
<!--#
AddPostRenderCallback(ctx, function() {
//code to execute
});
_#-->
There is another way to achieve this by using:
ctx.OnPostRender = function() {
};
Explore Item Display Template
Now let's open Item Display Template from Display Templates --> Content Web Parts folder.
Header Properties
In Item Template Header Property <mso:ManagedPropertyMapping> is used to map Search Managed Properties, retrieved from search query and map them to fields on Item Display template.
<mso:ManagedPropertyMapping msdt:dt="string">'Picture URL'{Picture URL}:'PublishingImage;PictureURL;PictureThumbnailURL','Link URL'{Link URL}:'Path','Line 1'{Line 1}:'Title','Line 2'{Line 2}:'Description','Line 3'{Line 3}:'','SecondaryFileExtension','ContentTypeId', 'FileExtension'{FileExtension}:'FileExtension'</mso:ManagedPropertyMapping>
In order to use a Search Managed Property, it should be first added under ManagedPropertyMapping header. To get a list of all Managed Properties that are returned from Search query, I took a fiddler trace while testing query on CSWP. Properties under ResultRows element are returned by search query in JSON format and can be used in Display Template.
mso:ManagedPropertyMapping: This property takes the managed properties that are used by search and maps them to values that can be used by the Display Template. The property is a comma-delimited list of values that uses the following format: 'property display name'{property name}:'managed property. For example: 'Picture URL'{PictureURL}:'PublishingImage;PictureURL;PictureThumbnailURL'.
For more Information about Mapping Input Properties checkout https://msdn.microsoft.com/en-us/library/jj945138.aspx#bk_mapproperties
Same as Control Template, Item Template also has Script Block and Outer DIV with matching DIV ID as template name.
DIV Block
Scripting should be put under outer DIV. After you map a property in header, you can get its value in script by using the following code:
var pictureURL =$getItemValue(ctx, "Picture URL");
The second parameter that is passed to $getItemValue() must match the property display name in single quotes used in the ManagedPropertyMapping element. In this example, Picture URL is the property name that is passed to $getItemValue(). Following code shows DIV section from my custom Item template.
<div id="Item_PictureJSlider">
<!--#_
var encodedId = $htmlEncode(ctx.ClientControl.get_nextUniqueId() + "_picture3Lines_");
var linkURL = $getItemValue(ctx, "Link URL");
linkURL.overrideValueRenderer($urlHtmlEncode);
var line1 = $getItemValue(ctx, "Line 1");
var pictureURL = $getItemValue(ctx, "Picture URL");
var containerId = encodedId + "container";
var dataDisplayTemplateTitle = "ItemPicture3Lines";
_#-->
<divclass="cbs-sliderContrainer"id="_#= containerId =#_"data-displaytemplate="_#= $htmlEncode(dataDisplayTemplateTitle) =#_">
<ahref="_#= linkURL =#_"title="_#= $htmlEncode(line1) =#_"target="_blank">
<imgsrc="_#= pictureURL =#_"width="570"height="270">
</a>
</div>
</div>
In above example ,all items returned by search will be rendered using HTML in inner DIV with class "cbs-sliderContrainer". Following screenshot is of rendered Display Template using IE developer tool (F12) . Notice DIVs with class "cbs-sliderContrainer", these are items coming from Item Template and they are wrapped in outer DIV class "slides" which is coming from Control template.
This post builds basics of Display Templates, my next post will focus on using JQuery Plugin to customize Display Templates!
Comments
Anonymous
January 01, 2003
Hi Swati, "picture3Lines" is just a static string to generate encodedId, which i have used to generate Div Id. you can use any string here, this will be helpful when using jquery to find an element within DOM. checkout part 2 for more details on using JQuery blogs.technet.com/.../sharepoint-2013-customize-display-template-for-content-by-search-web-part-cswp-part-2.aspxAnonymous
January 01, 2003
Hi
In the case of a cloned OOTB Slideshow display template I wondered if it was possible to dynamically change it the web part tool panel settings via a post back function so the slide show can adjust what is displayed in response to the number of items returned...Anonymous
January 01, 2003
Thanks Suresh! Glad you liked it!Anonymous
January 01, 2003
Thank you Tahir! I am glad you liked it!Anonymous
January 01, 2003
Glad you like it! Thanks!Anonymous
January 01, 2003
Hi Siraj, thanks for explaining Display templates !! Please clarify about following lines <div id="Item_PictureJSlider"> <!--#_ var encodedId = $htmlEncode(ctx.ClientControl.get_nextUniqueId() + "picture3Lines"); here what is picture3Lines? how to get this value? regards, SwatiAnonymous
January 01, 2003
Excellent article on display templates.
ThanksAnonymous
September 02, 2013
Good Work!!!Anonymous
September 24, 2013
Good post.. Thank you..Anonymous
September 24, 2013
Very awesome, Siraj!Anonymous
December 13, 2013
Extremely good post, very helpful indeed :) A question: I need to display a user thumb in a list that displays recent blog posts, however I cannot figure out how to get the actual user thumb that resides on MySite, all I've accomplished so far is to display the "dummy" author thumb. Hope you can point me in the right direction. regards ThomasAnonymous
January 28, 2014
how can I call a javascript function from an anchor tag clickAnonymous
January 31, 2014
hi karan, this is a custom anchor tag inside display template.sortByDate() is a js functionAnonymous
March 19, 2014
Nice Blog Very Help fulAnonymous
April 03, 2014
This has been asked many times but I never found any explanation. If I want to render groups similar to how the CQWP allowed grouping where exactly would I do that. I assume it would have to be created in the Item template but I have not seen any examples. I am aware that there is a Group template but I don't know how to specify one. Without grouping the display the CSWP is not very useful since you may want to rollup content from many locations and group the results in a single CSWP. I have worked around this by refining the results into multiple CSWPs and than tabifying those but thats not dynamic at all. Any ideas or resources you could point me at. Thanks in advance.Anonymous
August 04, 2014
Hi,
How to call javascript function in the anchor tag in the search display template.
ThanksAnonymous
September 17, 2014
Q: Show the custom popup window on clicking the people name in sharepoint people search result
We are doing the below code to open a popup but while clicking on name link its postback the page and not opening the popup in first click but opening in second click.The same issue occurs while navigate to second page using pagination
The below code used to show name in item template
button id="Name FieldLink" class="temp" style="font-size: 12px;text-decoration:none;color:#0072c6;border:0px solid #fff;background:transparent;margin-left: 1px;height: 15px;padding: 0 10px 17px 0px;text-align: left;cursor:pointer;font-family: Arial, Helvetica, sans-serif;" title="">#= DisName =#
The below jquery code used to open popup in control search template
ctx.OnPostRender = [];
ctx.OnPostRender.push(function () {
$(".temp").on("click", function(event)
{
event.preventDefault();
$('#fadeout').show();
$('#pop1').find('.tab-content-people').html($(this).closest('.emp-card').find('.pop-content').html());
$('#pop1').show();
return false;
});
});Anonymous
November 10, 2014
Extremely good article about display template !!!Anonymous
November 13, 2014
How come my outer DIV does render as empty DIV when it in fact shouldn't?Anonymous
January 06, 2015
The comment has been removedAnonymous
March 30, 2015
Thank you, Siraj. This was exactly what I needed to add the rollup image to my display results. Much appreciated!Anonymous
April 29, 2015
Siraj:
I like your detailed article. Can we do all this in O365? Please let me know what is possible with O365 and what is not.
Thanks.
SabeehAnonymous
April 29, 2015
Hi Siraj, How can we get the Number of counts in the display template using content search webpart? Let me know if this is possible in sharepoint online.
ThanksAnonymous
April 29, 2015
Hi sorry i just mispelled it number oc comments for a blog post in the display template using CSWP in sharepoint onlineAnonymous
November 26, 2015
Good work, like your explaination Siraj.