Wednesday, November 16, 2016

Displaying a random SharePoint Search result using Display Templates

On a recent project I had the requirement to randomly display a staff profile on the home page of the Intranet. The staff profile would provide some basic details of the person (with a head shot), then on clicking the item the user would be redirected to a page that displayed a bunch of fun questions and the person's response to each question. The web page used its own custom page layout and associated content type to store all of the answers.

Now we've probably all seen various custom developed web parts in the past, utilising calls to the User Profile Service or some other list via CAML queries. We've probably also seen Content Query Web Part solutions. For this project I was determined to leverage search as much as possible, reducing the continual queries to the backend data source. So my technical challenge was not in getting the results (as search query rules/result sources do a good job of that); but rather randomly selecting an item to display from the result pool.

So in order to make this magic happen, I went about with the idea of creating a custom group display template (i.e. to generate the seed) and a custom item template, whose job was to render the item if it was told to do so. So how do you do this? Quite simply, you add your own variables to the Search context!

In your control template, you put the following :

<!--#_
        var randomItem = 0;  // default to first item returned from search
        try {
            var totalResults = ctx.ListData.ResultTables[0].ResultRows.length; //get the total number of results returned
            if (!isNaN(totalResults))
            {
                randomItem = Math.floor(Math.random() * totalResults);
            }
            ctx.RandomItemNumber = randomItem;  // prime our own variable for the Item display template
        }
        catch (err) {
            console.log(err);
        }
_#-->

Then in your item template, you put the following around the outer part of the display template:

<!--#_
  var showItem = true;  // default to showing the item
  try
  {
       if (ctx.CurrentItemIdx != ctx.RandomItemNumber) {
                showItem = false;
       }
  }
  catch (err)
  {
       console.log(err);
  }
  if (showItem)
  {
 _#-->
...Your Item output rendering goes here...
<!--#_
  }
_#-->

I hope this helps someone - it took a little bit of playing around to discover how to get this working, but in the end it was really quite simple.

No comments: