PnP – Office 365 Starter Intranet Solution (Part 6: The search implementation)

PnP – Office 365 Starter Intranet Solution (Part 6: The search implementation)

Content type Blog Post
Author Franck Cornu
Publication Date 28 Mar, 2017
Reading Time Less than 1 minute

Archive and category pages management

An « archive » page is typically the page accessed by clicking on the « See all news » link at the bottom of a list or a carousel component. Instead of implementing a dedicated search page to display all the news, this feature is mutualized with the global search results page. At the end, it is only a refined query on the « Intranet » search category only for the « news » content type. This query is built dynamically like this:

ko.bindingHandlers.getNewsSearchUrl = {
init: () => {
let newsContentTypeId = “0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF39000650D0E024D0AE42B88AF5AF825F709C02”;
let refinementString = ‘{“k”:””,”r”:[{“n”:”ContentTypeId”,”t”:[“‘ + newsContentTypeId + ‘*”],”o”:”and”,”k”:false,”m”:null}’;
this.searchPageUrl(_spPageContextInfo.siteAbsoluteUrl + “/Pages/” + i18n.t(“intranetSearchPageUrl”) + “#Default=” + encodeURIComponent(refinementString));
},
};

You can apply the same behavior for pages, announcements, etc.

Notice I use a refinement query (« r » parameter) instead of a direct query (the « k » parameter) because I don’t want to show it in the search box and the search results (which are automatically grab the entered keywords via the « k » query string parameter).

A category page is slightly different than an archive page. It represents a page for a specific navigation node. For example, the « News » node is a category page and if you click on it you might expect to see all the news of the portal. Because, like archive pages, we don’t necessary want to put the whole refinement query in the navigation link property manually (because it can be very long and complex), we can use search query rules to simplify instead:

Note: If you don’t want to manage category pages, you can just leave blank the navigation link for concerned taxonomy terms.

Taxonomy refiners special case

For taxonomy refiners, I use the ows_taxid_xxx crawled properties instead of the « text » ones. Remember, in the previous article, I said refiners were not translated automatically by SharePoint so I want to get the term id and using code, get the right label according to the intranet current language.

It is done through a custom binding handler used in the display template:

function outputFilter(refinementName, refinementCount, refiners, method, aClass, showCounts) {

    var aOnClick = "$getClientControl(this)." + method + "('" + $scriptEncode(Sys.Serialization.JavaScriptSerializer.serialize(refiners)) + "');";

    var nameClass = “ms-ref-name ” + (showCounts ? “ms-displayInline” : “ms-displayInlineBlock ms-ref-ellipsis”); 

    var encodedRefinementName = $htmlEncode(refinementName);
    // Keep only terms (L0). The crawl property ows_taxid_xxx return term sets too.
    if (!/(GTSet|GPP|GP0)/i.test(encodedRefinementName))  { 
_#-->          
        <div id='Value' name='Item' class="refinement-filter">     
            <a id='FilterLink' class='_#= $htmlEncode(aClass) =#_' onclick="_#= aOnClick =#_" href='javascript:{}'>
                <div id='RefinementName' class='_#= nameClass =#_' data-bind="localizedTermLabel: '_#= encodedRefinementName =#_'"  ></div>
                ...
...
ko.bindingHandlers.localizedTermLabel = { 
    init: (element, valueAccessor) => {
        let value: string = ko.unwrap(valueAccessor()); 
        // Check if the value seems to be a taxonomy term
        let isTerm = /L0\|#/i.test(value);
        if (isTerm) {
            // Extract the id
            let termId: Array<string> = value.match(/[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}/);
            if (termId.length > 0) {
                $(element).addClass("spinner");
                this.taxonomyModule.init().then(() => {
                    this.taxonomyModule.getTermById(new SP.Guid(termId[0])).then((term) => {
                        $(element).text(term.get_name())
                        $(element).removeClass("spinner");
                    });
                }).catch((errorMesssage) => {
                    pnp.log.write(errorMesssage, pnp.log.LogLevel.Error);
                });
            }
        } else {
            // Return the original value
            $(element).text(value);
        }
    },
};

..

About the Author

Franck Cornu
– LinkedIn: HTTPS://CA.LINKEDIN.COM/IN/FRANCKCORNU
– Twitter: @FRANCKCORNU
– Blog: HTTP://THECOLLABORATIONCORNER.COM/

References

Cornu, F. (2016). PnP – Office 365 Starter Intranet Solution (Part 6: The search implementation) [online] Available at: http://thecollaborationcorner.com/2016/09/08/part-6-the-search-implementation/ [Accessed 24 Mar. 2017].