Creating a Result Block that Shows Office Graph Suggestions, Part 2: Technical Details

Elio Struyf

by Elio Struyf on 3/13/2015

Share this:
Print

Article Details

Date Revised:
3/17/2015

Applies to:
Display Template, Elio Struyf, Office Graph, search center, search results, SharePoint


In a previous article I showed you how to create a result block with Office Graph suggestions using three display templates. In this article I will describe in more detail what each of these templates does.

In my solution I created three display templates that I will explain in more detail below.

  • OfficeGraph_Results.html
  • Item_OfficeGraph_Result.html
  • Item_OfficeGraph_HoverPanel.html

Note: You can download the display templates from GitHub: Office Graph Result Block Templates.

Figure 1 shows the end result of these display templates

Office Graph search results in SharePoint Search results

Figure 1: Office Graph result block

OfficeGraph_Results.html - main template

This template makes the call to Office Graph to retrieve results. The template also renders the number of items you configured in the result block, it refines the results when a specific refinement is in place and it visualizes the search results on the page.

I will explain each aspect of this template in the next sections.

Total items to show in the result block

When configuring a result block, you can choose how many items you want to show in the result block. When you run a query, the result block will show only the number of items that you specified.

This scenario works a bit different because you use a REST call to retrieve the search results. That is also the reason why I use a "*" star query for the result block. You need to make sure that at least one result item gets returned. Once a result item for the result block is retrieved, the OfficeGraph_Results.js display template will get loaded.

Now because we are calling a REST service, you need to limit the number of results returned from your REST call.

Luckily you can check the CurrentGroup property to see the maximum items the result block may have.

ctx.CurrentGroup.RowCount

This property value will be appended to the REST query URL to set the RowLimit property.

Only call the REST service once

You only want to call the REST service the first time the display template gets loaded and not for each result that is retrieved in the result block.

Note: The control template will execute the item template for each result. So when three results are retrieved, the template will get executed three times.

To solve this problem, I added a processCount variable which gets incremented each time the template gets executed. The REST call is only called the first time the first result gets rendered. The other times it will not do anything. I solve this problem using the following code:

// Get number of items to show in the Result Block
resultCount = currentCtx.CurrentGroup.RowCount;

// Get results from Office Graph
if (processCount === 1) {
    // Get the current keyword
    keywords = currentCtx.DataProvider.get_currentQueryState().k;

    // Do the REST call to Office Graph
    AddPostRenderCallback(currentCtx, function() {
        get();
    });
} else {
    // Reset the process count when the last item is loaded
    processCount = processCount === resultCount ? 0 : processCount;
}

Refine the Office Graph results

Once you retrieve the results in your search center, you may want to refine the results. You can do this with the following code:

// Check if the results are refined
if (!$isNull(currentCtx.DataProvider.get_currentQueryState().r)) {
    var refiners = currentCtx.DataProvider.get_currentQueryState().r;
    // Check if multiple refiners are in place
    if (refiners.length === 1) {
        refinement = String.format("&refinementfilters='{0}'", refiners.toString());
    } else {
        refinement = String.format("&refinementfilters='and({0})'", refiners.toString());
    }
} else {
    refinement = "";
}

The code first checks if there is already some refining done on your results. If this is the case, the refiner's length will be checked. This check is required to allow multiple refinements on the result block (example: refine on file type and author). When there are multiple refiners in use, you should add an and property in order to make it work.

Retrieving the Office Graph results

There is nothing special about retrieving the Office Graph results. You can retrieve the results via an Ajax call to the search REST API.

var restUrl = String.format("{0}/_api/search/query?QueryText='({1}) AND (FileExtension:doc OR FileExtension:docx OR FileExtension:ppt OR FileExtension:pptx OR FileExtension:xls OR FileExtension:xlsx OR FileExtension:pdf)'&Properties='TitleBasedSummaries:true,GraphQuery:and(actor(me\\,action\\:1021)\\,actor(me\\,or(action\\:1021\\,action\\:1036\\,action\\:1037\\,action\\:1039))),GraphRankingModel:action\\:1021\\,weight\\:1\\,edgeFunc\\:weight\\,mergeFunc\\:max'&SelectProperties='Author,AuthorOwsUser,DocId,EditorOwsUser,FileExtension,FileType,HitHighlightedProperties,HitHighlightedSummary,LastModifiedTime,LikeCountLifetime,ListID,ListItemID,OriginalPath,Path,Rank,SPWebUrl,SiteTitle,Title,ViewCountLifetime,siteID,uniqueID,webID,SecondaryFileExtension'&hithighlightedproperties='Title,Path'&RankingModelId='0c77ded8-c3ef-466d-929d-905670ea1d72'&RowLimit={2}&StartRow=0&BypassResultTypes=true{3}&ClientType='OfficeGraphTemplate'", _spPageContextInfo.webAbsoluteUrl, keywords, resultCount, refinement);

Once the results are retrieved it gets interesting. If you ever did a REST call to the search API, you know that the JSON object you retrieve is not the same as that of the default search query. You do not have a ctx.ListData object or such. You can find the results in data.PrimaryQueryResult.RelevantResults.Table.Rows. So I created a CurrentItem object for each result that is retrieved. Doing it this way I can use the default display template rendering and functions.

// Create current item object
var currentItem = {};
currentItem = setFields(currentItem, result.Cells);

// Create CurrentItem object
var setFields = function (item, cells) {
    var i = cells.length;
    while (i--) {
        var cell = cells[i];
        item[cell.Key] = cell.Value;
    }
    return item;
};

Rendering the result HTML output

Now the fun part – rendering the Office Graph results onto your page. First I created a variable with my HTML markup and replaced the placeholders with the values I retrieved from search. This is just one  approach. Since we are working in a search center, we can also use display templates to do the rendering.

In order to use a display template to render the HTLM markup for your results from within the template, you first need to load the display template JavaScript file. You can do this from within the display template with this code:

// Load the display template for the Office Graph results
var templateUrl = "~sitecollection/_catalogs/masterpage/OfficeGraph/Item_OfficeGraph_Result.js";
RegisterSod('Item_OfficeGraph_Result.js', Srch.U.replaceUrlTokens(templateUrl));

EnsureScriptFunc("Item_OfficeGraph_Result.js", null, function() {
    templateFunc = Srch.U.getRenderTemplateByName(templateUrl, null);
});

The code registers and loads the template. Once the template is loaded, the display template function gets retrieved (Srch.U.getRenderTemplateByName). The approach is similar to how the default display templates get loaded. The function needs to be retrieved like this because the function names get automatically generated by SharePoint and contains a GUID in the name. Example: DisplayTemplate_82488fbf09274510b5e6618debdf3b80.

Important: The reference to the template needs to be updated to the location in your master page gallery.

Once the display template function is retrieved, you can use it to render the HTML markup like this:

// Set the current item to the context
currentCtx["CurrentItem"] = currentItem;

// Call the display template function to render the current item
resultsMarkup.unshift(CoreRender(templateFunc, currentCtx));

When all the HTML for the results are retrieved it gets added on the page.

Item_OfficeGraph_Result.html - Item display template

This display template renders the Office Graph results. It retrieves the values from the current item to process and places it in the HTML markup.

Important: This template uses a hover panel display template; be aware that the reference to the hover panel template needs to be changed to the location in your master page gallery.

Item_OfficeGraph_HoverPanel.html - Item hover panel display template

This template will be used to render the hover panel for the Office Graph results. Special thanks to Mikael Svenson for the Delve content search web part display templates. This hover panel template is based on one of his templates.


Topic: Enterprise Search

Sign in with

Or register