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.