Rendering Results from Multiple Item Display Templates in the CSWP

Elio Struyf

by Elio Struyf on 5/22/2015

Share this:
Print

Article Details

Date Revised:
5/22/2015

Applies to:
Content Search Web Part, CSWP, display templates, item display template, routing template, Search Result Web Part


A few weeks ago a customer asked me if it was possible to create a display template that visualizes article results according to the page layout that got used. This customer has various types of articles and page layouts set up in their environment. The display template was required for the main roll-up of the articles and users had to have the same experience as going to the article itself.

Note: The approach that is described in this article is not limited to only page layouts. You can use the approach for other managed property values. For example, if you want to visualize the results accordingly from the site location they were retrieved or based on their content type.

Problem

When you want to visualize search results, the easiest approach is to use the Content by Search Web Part (CSWP), but there is one major problem when using this web part. The CSWP allows you to define only one item display template. That means that you need to define all the styles into one item display template. Depending on the number of styles you have to define, this item display template would get enormous and it gets difficult to maintain.

A better approach would be to have a display template for each style like you could do with result types for the Search Result Web Part. Having multiple display templates makes it easier to maintain each individual styling, but it requires that you have a mechanism to load these templates.

One idea I had to load these templates was to create a template that I call the "routing" template. This routing template is an item display template that has a number of checks in place to load the right display template and render the results.

Note: Another approach is to use the Search Result Web Part and create result types for all the styles. Be aware that this approach could have an impact for the visualization of results in your search center (if you define them on the same level). The approach itself also requires some configuration to get everything correctly configured.

Routing template

As mentioned, the routing template is just an item template that contains a couple of checks. These checks all start with an array in which you define the managed property value and the matching template to load.

var defaultLayout = 'Item_BodyOnly.js'; var layouts = { 'PageFromDocLayout.aspx' : 'Item_BodyOnly.js', 'ArticleLeft.aspx' : 'Item_ImageLeft.js', 'ArticleRight.aspx' : 'Item_ImageRight.js', };
Next, you write the code to retrieve the display template that needs to get loaded from the array.

Important: you need to add the managed property you want to check to the ManagedPropertyMapping attribute. In this example PublishingPageLayoutOWSURLH is used. This managed property holds the page layout URL that got used for the article.

var pageUrl = $getItemValue(ctx, 'PublishingPageLayoutOWSURLH'); if (!pageUrl.isEmpty) { // Get the page name var url = pageUrl.value[0].value; if (!$isEmptyString(url)) { // Retrieve the corresponding display template var pageName = url.substring(url.lastIndexOf('/') + 1); // Retrieve the display template to load from the array var dtName = layouts[pageName]; // Check if a display template value is retrieved if ($isEmptyString(dtName)) { // Use the default display template dtName = defaultLayout; } /* NEXT CODE SNIPPET */ } }

On line 4, the page layout value is retrieved and looks like this:

http://site-url/_catalogs/masterpage/PageFromDocLayout.aspx

On line 7, the page name gets retrieved from the URL. This is required to get the display template, which is defined in the array.

Note: If you want to work with another managed property like the site location or content type, you have to define the values in the layouts array and modify the code to make it work for your managed property.

If the managed property value did not exist in the array (in this example, it would be a page result with a page layout that is not defined), a default layout gets set to visualize the result. This is done on lines 11 - 14.

Once you know the filename of the display template to load, you have to write the code to get the display template loaded. You can load the display template with the following code:

// Load the display template for the corresponding page layout var dtUrl = '~sitecollection/_catalogs/masterpage/Tests/'; var dtFullUrl = dtUrl + dtName; // Register the display template to load RegisterSod(dtName, Srch.U.replaceUrlTokens(dtFullUrl)); (function (id) { // Load the display template EnsureScriptFunc(dtName, null, function () { // Retrieve the display template function var templateFunc = Srch.U.getRenderTemplateByName(dtFullUrl, null); // Render the display template var markup = CoreRender(templateFunc, contexts[id]); // Render the markup retrieved from the template on the page render(markup, id); }); })(id);

On the second line, you define the location where your display templates can be found. Once the display template is loaded, the CoreRender function gets called, which will render the item mark-up. This mark-up needs to be added to the DIV element defined in the routing template; this is done by calling the render function on line 15.

var render = function (markup, id) { var elm = document.getElementById(id); if (!$isNull(elm)) { elm.innerHTML += markup; } };

The render function is nothing special; it retrieves the DIV element of the current item and appends the item display template mark-up to it.

Once the code is in place, you configure the CSWP to use routing template as the item display template.

Configure to load the routing template
Figure 1: Configure to load the routing template.

Here you can see a simple result output:

Routing template loaded and rendered three other templates
Figure 2: Routing template loaded and rendered three other templates.

Here I have three different item display templates: Item_BodyOnly.js, Item_ImageLeft.js, Item_ImageRight.js. In these display templates, I defined a block with a different background color, the display template filename and page title.

Adding managed properties

If you want to add new managed property mappings to one of the item display templates, you also have to add the same managed property mapping in your routing template. The reason for this is because the CSWP is not aware of your item display templates; it only knows the property mappings that are defined in the routing template.

Once the routing template is loaded, this template passes the current processed result with its managed properties to the item template.

Example

For example, if you map the author managed property in the Item_ImageLeft.html display template like this:

/* BEFORE */ <mso:ManagedPropertyMapping msdt:dt="string">'Path','Title':'Title'</mso:ManagedPropertyMapping> /* AFTER */ <mso:ManagedPropertyMapping msdt:dt="string">'Path','Title':'Title','Author':'Author'</mso:ManagedPropertyMapping>
You will also have to add this 'Author': 'Author' mapping in the Item_Routing.html display template:

/* BEFORE */ <mso:ManagedPropertyMapping msdt:dt="string">'PublishingPageLayoutOWSURLH','Path','Title':'Title'</mso:ManagedPropertyMapping> /* AFTER */ <mso:ManagedPropertyMapping msdt:dt="string">'PublishingPageLayoutOWSURLH','Path','Title':'Title','Author':'Author'</mso:ManagedPropertyMapping>

Once you have done this and you refresh the page, the Item_ImageLeft results should now include the author name.

Updated Item_ImageLeft.js template
Figure 3: Updated Item_ImageLeft.js template.

Download and using the templates

You can find the templates I created for this article on the SPCSR repository on GitHub: Loading and rendering other display templates.

If you want to use the templates, make sure to update the defaultLayout variable and layouts array in the Item_Routing.html display template.

You can find Elio's original blog post here.


Topic: Development - Recent

Sign in with

Or register