Showing Search Results in a grid using DataTables.js

April 23, 2014 — 3 Comments

datatable

This might be one of the coolest JavaScript libraries out there for SharePoint, DataTables.js. DataTables.js allows you render a set of search results in data table format allowing you to Sort, Filter and Page automatically. Because SharePoint search allows you to search and return items from the entire farm you lost the ability to dynamically sort and quickly filter. DataTables give you this back in a very quick and easy to use format. To get data tables working we need the following:

  • jQuery library reference
  • DataTables library reference
  • DataTables base or custom css style sheet
  • Custom Control Template
  • Custom Item Template

Let’ s get started. First we need to created out custom control and item templates. These templates are created and stored at the site collection level. They are saved in the Master Page Gallery > Display Templates > Content Web Parts To create these two files you need to create two HTML files. This can be done by either copying an existing item and control template and replacing the code with the code below OR you can copy and paste this code directly into a new HTML file(s). Control Template Copy and paste the following code into a new Control_Grid.html file


<code><html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"> <head> <title>Datatable</title> <!--[if gte mso 9]><xml> <mso:CustomDocumentProperties> <mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden> <mso:MasterPageDescription msdt:dt="string">This is the default Control Display Template that will list the items. It does not allow the user to page through items.</mso:MasterPageDescription> <mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106601</mso:ContentTypeId> <mso:TargetControlType msdt:dt="string">;#Content Web Parts;#</mso:TargetControlType> <mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated> <mso:HtmlDesignConversionSucceeded msdt:dt="string">True</mso:HtmlDesignConversionSucceeded> <mso:HtmlDesignStatusAndPreview msdt:dt="string">http://demo.spphile.com/sites/tcf/_catalogs/masterpage/Display Templates/Content Web Parts/Control_Grid.html, Conversion successful.</mso:HtmlDesignStatusAndPreview> </mso:CustomDocumentProperties> </xml><![endif]--> </head> <body> <!-- Warning: Do not try to add HTML to this section. Only the contents of the first <div> inside the <body> tag will be used while executing Display Template code. Any HTML that you add to this section will NOT become part of your Display Template. --> <!-- Use https://datatables.net/styling/themes for datatable themes --> <script> $includeScript(this.url, "http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.0.min.js"); $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js"); $includeScript(this.url, "http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.datatables.min.js"); $includeCSS(this.url, "http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.datatables.css"); </script> <!-- Use the div below to author your Display Template. Here are some things to keep in mind: * Surround any JavaScript logic as shown below using a "pound underscore" (#_ ... _#) token inside a comment. * Use the values assigned to your variables using an "underscore pound equals" (_#= ... =#_) token. --> <div id="Control_List"> <!--#_ if (!$isNull(ctx.ClientControl) && !$isNull(ctx.ClientControl.shouldRenderControl) && !ctx.ClientControl.shouldRenderControl()) { return ""; } ctx.ListDataJSONGroupsKey = "ResultTables"; var $noResults = Srch.ContentBySearch.getControlTemplateEncodedNoResultsMessage(ctx.ClientControl); var noResultsClassName = "ms-srch-result-noResults"; var encodedId = $htmlEncode(ctx.ClientControl.get_nextUniqueId() + "_Table_"); var headerRowId = (encodedId + "_HeaderRow_"); ctx.managedPropertyNames = []; ctx.OnPostRender = []; ctx.OnPostRender.push(function () { $("#" + encodedId).dataTable({ "bPaginate": true, "bAutoWidth": false, "bSort": true, "bInfo": true }); });   var ListRenderRenderWrapper = function(itemRenderResult, inCtx, tpl) { var iStr = []; iStr.push(itemRenderResult); return iStr.join(''); } ctx['ItemRenderWrapper'] = ListRenderRenderWrapper; _#--> <table id="_#= encodedId =#_" class="table table-hover"> <thead> <tr id="_#= headerRowId =#_" class="resultsTableHeader"> <th>Title</th> <th>Modified</th> </tr> </thead> _#= ctx.RenderGroups(ctx) =#_ </table> <!--#_ if (ctx.ClientControl.get_shouldShowNoResultMessage()) { _#--> <div class="_#= noResultsClassName =#_">_#= $noResults =#_</div> <!--#_ } _#--> </div> </body> </html>

As you can see above, the necessary jQuery libraries and CSS are being referenced in the script tag. If you want you can download these files and drop them into your master page gallery and allow your BLOB cache to cache these files. Otherwise, your search display template is going to make a call for these files every time this template is used and rendered. Next, we need to create our item template. Do so by copying and pasting the code below into a new file called Item_DataRow.html
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"> <head> <title>Data Row</title> <!--[if gte mso 9]><xml> <mso:CustomDocumentProperties> <mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden> <mso:ManagedPropertyMapping msdt:dt="string">'Link URL'{Link URL}:'Path','Line 1'{Line 1}:'Title','Line 2'{Line 2}:'','FileExtension','SecondaryFileExtension'</mso:ManagedPropertyMapping> <mso:MasterPageDescription msdt:dt="string">This Item Display Template will show a small thumbnail icon next to a hyperlink of the item title, with an additional line that is available for a custom managed property.</mso:MasterPageDescription> <mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106603</mso:ContentTypeId> <mso:TargetControlType msdt:dt="string">;#Content Web Parts;#</mso:TargetControlType> <mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated> <mso:HtmlDesignConversionSucceeded msdt:dt="string">True</mso:HtmlDesignConversionSucceeded> <mso:HtmlDesignStatusAndPreview msdt:dt="string">http://demo.spphile.com/sites/tcf/_catalogs/masterpage/Display Templates/Content Web Parts/Item_DataRow.html, Conversion successful.</mso:HtmlDesignStatusAndPreview> </mso:CustomDocumentProperties> </xml><![endif]--> </head> <body> <!-- Warning: Do not try to add HTML to this section. Only the contents of the first <div> inside the <body> tag will be used while executing Display Template code. Any HTML that you add to this section will NOT become part of your Display Template. --> <script> $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js"); </script> <!-- Use the div below to author your Display Template. Here are some things to keep in mind: * Surround any JavaScript logic as shown below using a "pound underscore" (#_ ... _#) token inside a comment. * Use the values assigned to your variables using an "underscore pound equals" (_#= ... =#_) token. --> <div id="DataRow"> <!--#_ var encodedId = $htmlEncode(ctx.ClientControl.get_nextUniqueId() + "_2lines_"); var linkURL = $getItemValue(ctx, "Link URL"); linkURL.overrideValueRenderer($urlHtmlEncode); var iconURL = Srch.ContentBySearch.getIconSourceFromItem(ctx.CurrentItem); var line1 = $getItemValue(ctx, "Line 1"); var line2 = $getItemValue(ctx, "Line 2"); line1.overrideValueRenderer($contentLineText); line2.overrideValueRenderer($contentLineText); var containerId = encodedId + "container"; var pictureLinkId = encodedId + "pictureLink"; var pictureId = encodedId + "picture"; var dataContainerId = encodedId + "dataContainer"; var line1LinkId = encodedId + "line1Link"; var line1Id = encodedId + "line1"; var line2Id = encodedId + "line2"; _#--> <tr> <td><a href="_#= linkURL =#_" title="Click here to see this item">_#= line1 =#_</a></td> <td>_#= line2 =#_</td> </tr> </div> </body> </html>

Ok, now we have two files Control_Grid.html and Item_DataRow.html. We need to get them into the Display Templates > Content Web Part gallery. We can do this several different ways. Do whichever options is easiest for you.

  • Map a drive to the master page gallery and drop the files into the Display Templates > Content Web Parts folder. (More Information)
  • Use SharePoint designer to drop the files into the Display Templates > Content Web Parts

Note: You only need to create and place the HTML files. SharePoint will automatically generate the respective JS files. Next we can setup a actual content by search web part to use our new control and item template.

  1. Place a Content Search web part on the page and define a query to get your needed results.
  2. In the web part properties set the Control and Item template to the new templates we just created and uploaded
  3. Next, click on the change property mappings and pick the fields that you want to be displayed.
  4. Save the page and you are done

Note: This template supports a total of 2 fields. You can add more fields to the Item_DataRow.html display template by adding more managed property mappings.

3 responses to Showing Search Results in a grid using DataTables.js

  1. 

    Hello Kameron. Wanted to know if you were successful in displaying more than 50 entries using display templates/datatables? Trying to find a way to bind the datatable control to display more items.

    Like

Leave a comment