This is the second post in a series I will be writing on the Content by Search Web Part (aka CSWP).
- What you get in the box
- Going Old Skool with XSLT
- Packaging & Deployment in Visual Studio
So if you’ve read Part 1 (what you get in the box) then you should have a pretty good idea of what the CSWP can do by now and what Display Templates and Property Mappings are (if you don’t then go back and read Part 1 .. I won’t be explaining them again).
So now we move onto the brave new world of building and defining your own custom Display Templates. The first thing you need to know is that Display Templates are stored in the Master Page Gallery (No, I don’t know why) specifically in a sub-folder called “Display Templates”.
|Item Templates in the Master Page & Page Layouts Gallery|
In here you will find two types of file:
- HTML files – these are the actual Display Templates (and what you will copy/create when you create your own custom template)
The out of the box display template files actually include some pretty useful comments which tell you how this works, but basically you have two “tokens” that you need to use:
<!–#_ var myString = ‘Hello World’; _#–>
<!–#_ var linkURL = $getItemValue(ctx, “Link URL”); _#–>
In the above example “Link URL” is the name of the Property Mapping. If you then want to use those variables in your HTML you simply wrap then in =#_ and _#= tokens. For example:
<a href=”_#= linkURL =#_”>
<span> _#= myString =#_</span>
It really is that simple!
But before we look at actually creating a new Display Template, what we really need is a problem to solve (I find it helps to focus the mind) ..
A suitable problem – Pictures, Publishing Pages and Image Renditions, oh my!
One of the great new features in SharePoint 2013 is “Image Renditions” (explained in great detail by Waldek Mastykarz). The cool thing is that if you have registered an Image Rendition with a desired width / height then you can include those as URL attributes and SharePoint will resize the image server side! This is a fantastic feature, it (drastically) reduces image sizes and ensures that the output is consistently rendered.
The out of the box display templates will automatically use these Image Renditions (the “Large Picture” template for example will ask SharePoint for an image which is 468×220, which matches one of the out of the box image renditions).
However when you try to use Image Renditions with the CSWP then you get some pretty odd results. To demonstrate this I have uploaded 4 photos from one of my holidays a few years back. I then created a Publishing Page for each photo and selected different Image Renditions for each page.
I then displayed then using the CSWP using the “Large Picture” item template and here are the results:
|CSWP displaying the actual photos in the Asset Library|
|CSWP displaying the Publishing Pages (and pulling the associated image)|
As you can see the second one looks a bit screwy as all of the images are different sizes. So what on earth is happening? Well, on checking the URL for one of the images which is being returned I can see that the image URL is correctly picking up the including the Rendition ID that I picked on my publishing page.
This is bad, because when SharePoint renders an image it will first look for the RenditionID and if it finds one it will ignore the width and height attributes!
The solution – Custom Display Template
So first off, I went and downloaded a copy of the Item_LargePicture.html file (which I used as my starting point) and renamed it (to “Item_LargePictureFixed.html”).
The next thing to do is to rename the <title> attribute in the file. This is what gets used in SharePoint to identify the template in the CSWP web part properties.
<title>Large Picture (FIXED)</title>
Now, I also wanted to add some more detail to my display template as just showing the title wasn’t that great (bringing back the publishing date and author for the page would be cool) .. and it also allows me to demonstrate how the Property Mappings work.
So the next thing is to look for an XML element near the top of the file called mso:ManagedPropertyMapping. This contains all of the Property Mappings that the CSWP will pick up when your template is in use.
When you define Property Mappings you can also define the search properties it should look for and the format you need to use is:
<Mapping Name>:<Search Property1>;<SearchProperty2>
Each mapping is separated by a comma (,) so my custom mappings were
- Image Title (mapped to “Title”)
- Image Date (mapped to “ImageDateCreated” and “LastModifiedTime”)
- File Author (mapped to “Author”)
‘Image Title’:’Title’,’Image Date’:’ImageDateCreated;LastModifiedTime’,’File Author’:’Author’
Don’t forget that our properties map to Search Properties .. so if the field isn’t being indexed by Search then you won’t be able to use it!
var pictureURL = $getItemValue(ctx, “Picture URL”);
// get the picture URL as a string
var cleanPictureURL = pictureURL.toString();
// check if it contains any query string arguments
if(cleanPictureURL .indexOf(“?”) != -1)
// if it does, then strip them out
var renditionIndex = cleanPictureURL .indexOf(“?”);
cleanPictureURL = cleanPictureURL .substring(0, renditionIndex);
// add the width/height attributes back in for the image renditions
cleanPictureURL = cleanPictureURL + “?width=468&height=220”;
// get our three other property values
var imageTitle = $getItemValue(ctx, “Image Title”);
var imageDate = $getItemValue(ctx, “Image Date”);
var fileAuthor = $getItemValue(ctx, “File Author”);
Once that was done all we needed was to make sure our variables were used in the right parts of the HTML. I then uploaded the HTML file (which effectively installs the new Display Template) and wired it up in the Web Part.
|New Display Template with new Property Mappings being displayed|
|New “fixed” Display Template with correct sized images, and new property mappings being displayed|
If you want to take a closer look then you can download the example HTML file here:
So that is it for CSWP Display Templates .. in part three we will look at going old school with XSLT rendering.