Result templates
Result templates
This is for:
DeveloperResult templates determine the format of the individual query results in a search interface. They’re embedded within a specific result layout, and a given template can only apply when its parent layout is selected.
When a query is successful, each result is rendered according to the first template whose condition is satisfied by that result.
Using the prebuilt templates
The JavaScript Search Framework includes several prebuilt result templates for common content types (for example, Salesforce, Jira, Khoros Community). You can use these templates in your search interface by including the templates.js
script after the framework script:
<script class="coveo-script" src="https://static.cloud.coveo.com/searchui/v2.10120/js/CoveoJsSearch.Lazy.min.js"></script>
<!-- ... -->
<script src="https://static.cloud.coveo.com/searchui/v2.10120/js/templates/templates.js"></script>
Registering your own templates
You can register custom result templates instead of using the prebuilt ones.
To register a custom template for a given result layout, you must embed a script
tag in that layout (that is, in the corresponding ResultList
component).
The script
tag must have the class="result-template"
attribute and a type
attribute that specifies which template engine to use. Each custom template1 that’s registered within a given ResultList
should also have a unique condition.
<div class="CoveoResultList" layout="list">
<script id="myPDFResultTemplate" class="result-template"
type="text/html" data-field-filetype="pdf">
<!-- ... -->
</script>
</div>
<div class="CoveoResultList" layout="card">
<script id="myVideoResultTemplate" class="result-template"
type="text/html" data-field-filetype="video">
<!-- ... -->
</script>
</div>
<div class="CoveoResultList" layout="table">
<script id="myDocumentResultTemplate" class="result-template"
type="text/html" data-field-filetype="doc">
<!-- ... -->
</script>
</div>
1: With the possible exception of the default template.
Designing a template
The JavaScript Search Framework supports two template engines along with built-in styling classes, components, and helpers, allowing you to conveniently design your own templates for the various result layouts that are available in a search interface.
Choosing a template engine
Result templates can use either the HTML engine (recommended) or the Underscore engine. You specify the template engine in the template script
tag (that is, type="text/html"
or type="text/underscore"
).
- We strongly recommend that you avoid using both the HTML and Underscore engines in the same template. When the two engines are used together, Underscore conditions are evaluated first, and HTML conditions are evaluated next. This can result in complex behaviors that are difficult to debug.
- The HTML and Underscore engines both support JavaScript Search Framework result template components. If your use case is fulfilled by a preexisting component, you should use it instead of implementing your own custom component or using inline JavaScript.
Using the HTML engine (recommended)
HTML result templates are entirely based on JavaScript Search Framework result template components. They can be executed inside environments with strict content security policies (for example, Salesforce with Lightning Locker enabled).
<script id="myTemplate" class="result-template"
type="text/html">
<div class="coveo-result-frame">
<div class="coveo-result-row">
<div class="coveo-result-cell"
style="<!-- ...some styling... -->">
<span class="CoveoIcon"></span>
<div class="CoveoQuickview"></div>
</div>
<div class="coveo-result-cell"
style="padding-left:15px;">
<div class="coveo-result-row">
<div class="coveo-result-cell">
<a class="CoveoResultLink"
style="font-size:18px;"></a>
</div>
<div class="coveo-result-cell"
style="<!-- ...some styling... -->">
<span class="CoveoFieldValue"
data-field="@date"
data-helper="date"></span>
</div>
</div>
</div>
</div>
</div>
</script>
If needed, you can expand the capabilities of HTML templates by developing your own custom components.
Using the Underscore engine
Underscore result templates are extremely flexible because they can execute arbitrary JavaScript code. However, they may not be compatible with, or secure enough for, strict content security policies or setups (for example, Salesforce with Lightning Locker enabled). Moreover, Underscore templates can become hard to read and difficult to maintain. They can also result in longer rendering times.
<script id="myTemplate" class="result-template"
type="text/underscore">
// Use a Coveo helper to format the date and time,
// referencing the raw.sysdate property of each result.
<div class="my-date"><%= dateTime(raw.sysdate) %></div>
// Output the excerpt of the result in a div.
<div class="my-excerpt"><%= excerpt %></div>
</script>
Instead of using Underscore templates, consider using HTML templates and developing your own custom components.
While reading the Underscore template engine documentation, you may notice that you can modify the delimiters (<% %>
) by changing the _.templateSettings
object.
However, changing these delimiters can cause issues with the JavaScript Search Framework, as they’re used internally. The JavaScript Search Framework offers alternative delimiters ({{ }}
), which work the same way as the default delimiters.
This can also be useful when using the JavaScript Search Framework with certain other technologies, such as ASP.NET or JSP, which use the <% %>
characters to let the server interpret expressions.
Creating a list layout template
This is the default layout for search results. When creating a custom result template, we recommend that you use the standard styling classes to organize your template into a grid.
Your template will include a number of result template components. The JavaScript Search Framework offers a variety of standard components, and you can also develop your own custom components if needed.
<div class="CoveoResultList" layout="list">
<script id="myListTemplate" class="result-template"
type="text/html" data-layout="list">
<div class="coveo-result-frame">
<div class="coveo-result-cell"
style="<!-- ...some styling... -->">
<span class="CoveoIcon" data-small="true"
data-with-label="false"></span>
<div class="CoveoQuickview"></div>
</div>
<div class="coveo-result-cell"
style="<!-- ...some styling... -->">
<div class="coveo-result-row"
style="margin-top:0;">
<div class="coveo-result-cell"
style="<!-- ...some styling... -->">
<a class="CoveoResultLink"></a>
</div>
<div class="coveo-result-cell"
style="<!-- ...some styling... -->">
<div class="coveo-result-row">
<span class="CoveoFieldValue"
data-field="@date"
data-helper="date"></span>
</div>
</div>
</div>
<div class="coveo-result-row"
style="margin-top:10px;">
<div class="coveo-result-cell">
<span class="CoveoExcerpt"></span>
</div>
</div>
<div class="coveo-result-row"
style="margin-top:10px;">
<div class="coveo-result-cell">
<span class="CoveoFieldValue"
data-field="@author"
data-text-caption="Author"
style="margin-right:30px;"></span>
<span class="CoveoFieldValue"
data-field="@source"
data-text-caption="Source"
style="margin-right:30px;"></span>
<span class="CoveoFieldValue"
data-field="@language"
data-text-caption="Language"
style="margin-right:30px;"></span>
<span class="CoveoFieldValue"
data-field="@filetype"
data-text-caption="File Type"
style="margin-right:30px;"></span>
</div>
</div>
<div class="coveo-result-row"
style="margin-top:10px;">
<div class="coveo-result-cell">
<div class="CoveoPrintableUri"></div>
</div>
</div>
<div class="coveo-result-row">
<div class="coveo-result-cell">
<div class="CoveoMissingTerms"></div>
</div>
</div>
</div>
</div>
</script>
</div>
Creating a card layout template
The JavaScript Search Framework offers two card layout-specific components that you can only use in Card layout result templates:
Using the CardActionBar
component
The CardActionBar
component renders a bar at the bottom of a card. Its primary use is to display action buttons for the result in which it embeds itself.
To add a CardActionBar
, insert the component as the last element in a coveo-result-frame
element.
<div class="CoveoResultList" data-layout="card">
<script id="myCardTemplate" class="result-template"
type="text/html">
<div class="coveo-result-frame">
<!-- ... -->
<div class="CoveoCardActionBar">
<div class="CoveoQuickview"></div>
<div class="my-custom-button"
onclick="alert('Hello, world!')">Click me!</div>
</div>
</div>
</script>
</div>
The prebuilt Card templates all feature the CardActionBar
component, which they usually populate with a Quickview
button and a CardOverlay
component.
Using the CardOverlay
component
The CardOverlay
component should be used inside the CardActionBar
component. It displays complementary information about a result.
The CardOverlay
component works by :
-
Finding all of its child DOM nodes.
-
Creating a hidden overlay containing these nodes.
-
Displaying a toggle button to show the overlay.
<div class="CoveoResultList" data-layout="card">
<script id="myCardTemplate" class="result-template"
type="text/html">
<div class="coveo-result-frame">
<!-- ... -->
<div class="CoveoCardActionBar">
<div class="CoveoQuickview"></div>
<div class="CoveoCardOverlay" data-title="Open me"
data-icon="replies">
<!-- ...overlay content... -->
<div class="CoveoText"
data-value="Here is some additional info."
style="margin:5px;"></div>
</div>
</div>
</div>
</script>
</div>
When the end user opens or closes the CardOverlay
component, it triggers an openCardOverlay
or closeCardOverlay
event, which you can bind to any handler. This is useful if you only want to execute actions when the end user opens or closes the overlay.1
1: For example, the ResultFolding
component uses the openCardOverlay
event to fetch additional results when the end user opens the overlay.
Creating a table layout template
The JavaScript Search Framework allows you to customize the header and footer of your table using the role
option.
To specify a role, add a data-role="table-header"
or data-role="table-footer"
attribute to the script
tag of your result template.
<div class="CoveoResultList" data-layout="table">
<script id="myTableHeader" class="result-template"
type="text/html" data-role="table-header">
// Any styling you add to the header
// affects the rest of the table.
<th style="width:40%;">Link</th>
<th>Description</th>
<th>URL</th>
<th style="width:20%;"
class="CoveoSort coveo-table-header-sort"
data-sort-criteria="date ascending,date descending"
data-display-unselected-icon="false"
data-caption="Date"></th>
</script>
// Because this template has no `data-role` attribute,
// it applies to each table row for your results.
<script id="myTableTemplate" class="result-template"
type="text/html">
<td><a class="CoveoResultLink"></a></td>
<td><span class="CoveoExcerpt"></span></td>
<td><span class="CoveoFieldValue"
data-field="@uri"></span></td>
<td><span class="CoveoFieldValue"
data-field="@date"
data-helper="date"></span></td>
</script>
// You can also add a template
// whose `data-role` is `table-footer`.
</div>
By default, table headers and footers behave as follows:
-
If you don’t register any custom templates, the prebuilt Table template displays a table header with the default fields (that is, Result Link, Excerpt, and Date).
-
If you register a custom Table template but don’t register a separate table header template, the table header is hidden.
-
By default, the table footer is hidden.
-
If you register a custom table footer template, the table footer is displayed.
Assigning conditions to your templates
Whenever a query result must be rendered, the JavaScript Search Framework uses its condition evaluation mechanism to determine which result template to use. Each template should have a unique condition that can only be satisfied by the desired subset of results.
A condition can either be field-based (recommended) or written in JavaScript.
About the condition evaluation mechanism
For each query result, the custom result templates embedded inside the selected result layout (that is, in the selected ResultList
component) are evaluated in the order in which they appear in the markup. The first template whose condition is satisfied by the result applies.
If a result satisfies none of the custom template conditions, and if the prebuilt result templates are available, then the prebuilt templates are also evaluated until the query result satisfies a condition.
Using field-based conditions (recommended)
You can define a field-based condition by adding one or more data-field-<NAME>
attributes to the script
tag of a custom result template, where you replace <NAME>
with the name of the field on which you want to base the condition clause (for example, data-field-filetype
).
<div class="CoveoResultList" data-layout="list">
// If @filetype is "video":
<script id="myVideoResultTemplate" class="result-template"
type="text/html" data-field-filetype="video">
<!-- ... -->
</script>
// Else if @filetype is "doc" OR @filetype is "pdf":
<script id="myDocumentResultTemplate" class="result-template"
type="text/html" data-field-filetype="doc,pdf">
<!-- ... -->
</script>
// Else if @sfid contains any non-null value:
<script id="mySFIDResultTemplate" class="result-template"
type="text/html" data-field-sfid>
<!-- ... -->
</script>
// Else if @filetype is "html" AND @source is "mysource":
<script id="myHTMLResultTemplate" class="result-template"
type="text/html" data-field-filetype="html"
data-field-source="mySource">
<!-- ... -->
</script>
<!-- ...more result templates... -->
</div>
These conditions behave as follows:
-
In a single field-based clause with multiple values (for example,
data-field-filetype="doc,pdf"
), commas are interpreted as logicalOR
operators. -
A field-based clause with no specified values (for example,
data-field-sfid
) is interpreted as a non-null check against the target field. -
Distinct field-based clauses on the same template are joined with the
AND
logical operator.
Field-based conditions can be executed inside environments with strict content security policies (for example, Salesforce with Lightning Locker enabled), and they’re not likely to result in unrecoverable configuration errors.
Using JavaScript conditions
You can define a JavaScript condition by adding a data-condition
attribute to the script
tag of a custom result template.
Most conditions rely on field values. These are accessible from the raw
property of the current query result (for example, raw.filetype
).
<div class="CoveoResultList" data-layout="list">
// If @filetype is "image":
<script id="myImageResultTemplate" class="result-template"
type="text/html" data-condition="raw.filetype=='image'">
<!-- ... -->
</script>
// Else if @price is larger than 500:
<script id="myPriceResultTemplate" class="result-template"
type="text/html" data-condition="raw.price>500">
<!-- ... -->
</script>
<!-- ...more result templates... -->
</div>
JavaScript conditions are highly flexible, as they can evaluate arbitrary Boolean expressions. However, they may not be compatible with, or secure enough for, strict content security policies or setups (for example, Salesforce with Lightning Locker enabled).
These conditions can also make it more difficult to detect faulty logic, as there’s a greater margin for configuration errors. Moreover, it’s possible to configure JavaScript conditions with invalid syntax, which would prevent results from rendering.
Defining a default result template
A result template with no condition will always apply if it’s evaluated. You can use such a template as the default one for a given result layout by embedding it last within the desired ResultList
.
<div class="CoveoResultList" data-layout="list">
<script id="myVideoResultTemplate" class="result-template"
type="text/html" data-field-filetype="video">
<!-- ... -->
</script>
<script id="myPDFResultTemplate" class="result-template"
type="text/html" data-field-filetype="pdf">
<!-- ... -->
</script>
<!-- ...more result templates with conditions... -->
<script id="myDefaultResultTemplate" class="result-template"
type="text/html">
<!-- ... -->
</script>
</div>
Since the JavaScript Search Framework evaluates custom templates before the prebuilt ones, including a custom template with no condition in a ResultList
implies that the prebuilt templates will never apply for that layout.
Reference
Result template components
You can use result template components to customize how your results are displayed in your search interface.
The generated reference documentation for all publicly exposed components is available on GitHub.
To insert a component, add a div
element with the Coveo<COMPONENT>
class inside your template, where you replace <COMPONENT>
with the name of the component that you want to insert (for example, class="CoveoSort"
).
You must then define all of the required and/or desired options for that component by adding one or more data-<OPTION>
attributes to this element, where you replace <OPTION>
with the name of the option that you want to set (for example, data-sort-criteria
to set the sortCriteria
option for the Sort
component).
Sample component use case
You want to add the Quickview
component to your result template, and you always want the Quickview button to be visible, even if the body of an item is empty (that is, using the alwaysShow
option).
Inside the script
element of your result template, add the following line:
<div class="CoveoQuickview" data-always-show='true'></div>
Generic component list
Backdrop
Coveo JavaScript Search Framework 1.2126.4 (February 2017)
Renders a background image. This is useful for displaying information on top of a dynamic background in a card result.
Badge
Outputs a field value that’s displayed as a colored badge. This component inherits from the FieldValue
component.
Excerpt
Outputs an excerpt of the result with the keywords highlighted.
FieldTable
Displays a table with one or more FieldValue
components.
FieldValue
Outputs a clickable field value that can add a filter in queries.
FollowItem
Allows the end user to follow a particular item so that they receive email notifications whenever the item changes.
Icon
Outputs an icon related to the result type.
ImageFieldValue
Coveo JavaScript Search Framework 2.7023 (September 2019)
Renders an img
HTML tag from a field whose value points to the URL of an image file.
MissingTerms
Coveo JavaScript Search Framework 2.6459 (July 2019)
Renders a list of query terms that weren’t matched by the result item.
PrintableUri
Outputs the printable (or breadcrumb) URI for a result.
Quickview
Outputs the clickable Quick view button, which opens a modal window. This usually references a QuickviewDocument
component in its content template.
ResultActionsMenu
Coveo JavaScript Search Framework 2.4382.10 (July 2018)
Adds a floating menu which may contain components to execute actions related to the result (for example, Quickview
).
ResultAttachments
Allows you to display the attachments for a result, given that a Folding
component is present in the page and properly configured.
ResultFolding
Allows you to display folded results, given that a FoldingForThread
or Folding
component is present in the page and properly configured.
ResultLink
Transforms search result titles into clickable links that log usage analytics events.
StarRating
Coveo JavaScript Search Framework 2.7968.7 (January 2020)
Renders a five-star rating widget for use in commerce result templates.
Text
Embeds itself in a result template to output a simple text value. This is only useful in the Interface Editor.
Thumbnail
Automatically fetches the thumbnail of the result object and outputs an HTML img
tag from it.
YouTubeThumbnail
Automatically fetches the thumbnail of a YouTube video and outputs a clickable HTML img
tag from it.
Card layout-specific component list
CardActionBar
Coveo JavaScript Search Framework 1.2126.4 (February 2017)
Displays an action bar at the bottom of a card result.
CardOverlay
Coveo JavaScript Search Framework 1.2126.4 (February 2017)
Displays a button that the end user can click to toggle the visibility of an overlay on top of the result.
Deprecated component list
ResultRating
Enables the collaborative rating of items, based on a 5-star rating system.
ResultTagging
Allows end users to tag items, if tagging is enabled for your index.
Result template helpers
When using a FieldValue
component, you can use result template helpers to modify the way in which field values are displayed.
If the prebuilt helpers don’t meet your needs, you may want to create your own.
Helpers can be used with both the HTML and Underscore engines.
Sample helper use case
You want to display the value of the @edition
field in your result template, but you know that its value can be long. To ensure that it doesn’t exceed 30 characters when presented in the template, you decide to use the shorten
helper function.
- Using an HTML template:
<div class="CoveoFieldValue"
data-field="@edition"
data-helper="shorten"
data-helper-options-length="30">
</div>
- Using an Underscore template:
<%= shorten(edition, 30) %>
Result template styling classes
Coveo offers the following CSS classes for result templates:
-
coveo-result-frame
-
coveo-result-row
-
coveo-result-cell
Typically, result frames contain result rows, which contain result cells, which in turn contain result template components. Result cells can also contain their own result rows, which can then contain other result cells, and so on.
Template styling tips
-
Add the CSS classes to simple
div
elements. -
Only insert one
coveo-result-frame
element per result template. This frame should include all of the other elements of your result template. -
Use
coveo-result-row
elements inside of yourcoveo-result-frame
to separate the components into rows. -
Include one or more
coveo-result-cell
elements inside eachcoveo-result-row
. -
Insert result template components inside of the
coveo-result-cell
elements. You can use multiple components in the same cell. -
Optionally, you can add further
coveo-result-row
elements inside of acoveo-result-cell
. -
Optionally, you can add inline styling or special CSS classes that set the width or alignment of your result cells. You can also add CSS classes of your own and add additional styling rules.
What’s next?
Learn more about designing templates: