Coveo Result List Component

March 11, 2021

By David Austin

The Coveo Result List component is responsible for displaying the query results that come back from a query call. Whether it be part of Hive or JSUI or some other implementation, they're all called the same so finding it is simple. You're looking for a div tag that resembles this: <div class="CoveoResultList">.

Depending on which platform you're using, some attributes will already be enabled, where as others will be pulls from an internally built model. In the case of JSUI you'll notice the following attributes are called out already: Coveo Menu Styles

data-layout: affects the layout type, i.e. list, card, or table. It's extremely handy as you don't need to figure out the CSS for each style if you want but you do need to be cogniscent of which is used. Far to many times we've encountered search pages where the layout is set to list but the end design resembles a card style. As a result, the effort to make that happen was probably far more than necessary. Keep in mind, you're not limited to just one style per search page. Further down you'll find out how to utilize both.

data-wait-animation: determines which type of animation to display prior to results showing, i.e. fade, spinner or none.

data-auto-select-fields-to-include: depending whether you select true or false will determine whether Coveo pulls down a select set of fields or the entire set. JSUI defaults to true but you'll notice you can't see all the fields for a given item, which is why during development we suggest setting to false. Also to be aware, if you're using Coveo for Sitecore this value is ALWAYS false.

This isn't all of the options however as there are several others that depending on the desired design, can be extremely handy:

<p><code>data-enable-infinite-scroll</code>: default value is <em>false</em>.  Should be obvious what this allows, but if you're including <em></em>Pagination or <em></em>ResultsPerPage you'll want to remove these as they could cause complications, plus you don't need them if you're doing infinite scroll.</p>
<p><code>data-enable-infinite-scroll-waiting-animation</code>: default value is <em>true</em> but is only affected if the above is <em>true</em>. </p>
<p><code>data-infinite-scroll-page-size</code>: default is <em>5</em>.  This is a personal preference.  Usually no more than <em>10</em> is recommended.</p>
<p><code>data-enable-scroll-to-top</code>: default is <em>true</em>.  This enables or disables whether or not the page will scroll to the top when a facet is updated.  Handy if you have a long list of facets,  but if you have infinite scrolling enabled could be nausiating for the user if enabled.  Keep in mind not only what is scrolling but the device the user may be using as well.</p>

The Layout Options

Depending what you choose from above, you could, using out-of-the-box settings in JSUI like the following get three drastically different layouts. Keep in mind, these are the default layouts. You can push their design even further with your own custom HTML, CSS, and JavaScript.


    <div class="CoveoResultList" data-layout="list" data-wait-animation="fade" data-auto-select-fields-to-include="true"></div>
    <div class="CoveoResultList" data-layout="card" data-wait-animation="fade" data-auto-select-fields-to-include="true"></div>
    <div class="CoveoResultList" data-layout="table" data-wait-animation="fade" data-auto-select-fields-to-include="true"></div>

The List Layout

A straight-forward result item list is just that, a list. There's nothing much to it and is often the go-to layout style for most search pages, but it doesn't have to be.

Coveo Result List

The Card Layout

A simple card layout, by default, is setup to be a two column set of result cards. Simply by changing the width of each card in CSS, you can increase these to as many as desired.

Coveo Result Card

Utilizing the rules of what each card can look like, you can create a mosaic of information back to the user.

The Table Layout

A simple table layout has advanced layout options enabling you to style the header, the row, and the footer for the table.

Coveo Result Table

To generate the table header you would add the following script tag within the CoveoResultList table layout. Note that if you style a column a particular width, this will affect the rest of the table. The powerful part is you can also add things like sorting to each table header. Identifying a section as a header is done by adding data-role="table-header" to the script tag.


<script id="table-header" class="result-template" type="text/html" data-role="table-header">
    <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>

To generate a row, with the appriate fields, you'd add the following after the above script tag.


<script id="table-row" 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>

Similarly you can add styling for the footer, if you have one. You'd do this by changing the data-role="table-footer".

What About Those Script Tags?

Unless you stick with the default Coveo Search look and feel, you're going to want to style up your results. Inside each Result List, as you've seen above is a one or more <script> tags that have their own sets of rules to determine how information is rendered. The order of the <script> tags that go within the CoveoResultTemplate is very important. As an item is determined how to be presented, it's evaluated against the data attributes of the <script> elemement and once it meets those criteria it will be displayed, skipping all subsequent options. Think of it as a series of if / else statements as shown below


<div class="CoveoResultList" data-layout="list">
    // If @filetype is "pdf":
    <script id="pdf-templates" class="result-template" type="text/html" data-field-filetype="pdf">
        <!-- ... -->
    </script>
    // Else if @filetype is "sitecoreitem":
    <script id="item-templates" class="result-template" type="text/html" data-field-filetype="sitecoreitem">
        <!-- ... -->
    </script>
    // Else if @tracking-id (or any field) 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 "ExternalSource":
    <script id="myHTMLResultTemplate" class="result-template"  type="text/html" data-field-filetype="html" data-field-source="ExternalSource">
        <!-- ... -->
    </script>
</div>

You can even determine what results show up within based upon calculations using the data-condition attribute. So say something that might be a specific distance from someone or a above a certain price could be given a certain styling.

It obviously doesn't end there as even within those script tags, via underscore templates you can still do additional if / elese statements. The important thing to remember is you still need a "catch all" bucket for any items that don't fall into that category. Not to mention, if there are errors in your underscore templates it will drop down the the bottom of the list and, if that one too is broken, to the default Coveo result style.

Template Approaches

There are a couple ways to go about designing the templates for results. You can utilize Coveo Components, the preferred HTML Engine approach. Or you can use Underscore templates and have complete flexibility in your design. It comes down to a personal preference. Both have their pros and cons.

HTML Engine Approach

The preferred way, by Coveo, is to use the HTML Engine to display coveo result details. The challenge here is having to understand each Coveo component, the capabilities and requirements of each and then to stylize, override the default Coveo styling as needed. A detail list of the component makeup can be found here: Result Template Components

Underscore Templates

Within each <script> tag you are able to stylize each result by HTML, CSS, and JavaScript all within a flexible Underscore template. They're very powerful, but come with some notable cons. They might not meet your Content Security Policy as they rely on inline scripts and they can be cumbersome to maintain due to their less than optimal readability. If you have your own style and brand CSS / JS framework, this might be best as it's more like building from scratch than overriding what's already there.

Template Makeup

Regardless of which approach you take, there are some interesting ways you can speed up the development yet again by using template reuse. Say you have a template for meta data that is used across result types. Rather than copying that html into each segment, you can refer to it using the CoveoTemplateLoader. Below we created a generic template that you could use across types. Note: This script tag segment exists outside of the CoveoResultList section.


<script type='text/underscore' class='result-template' id='default-meta-template-table'>
    <div>
      <table class="CoveoFieldTable">
        <tr data-field="@author" data-caption="Author"></tr>
        <tr data-field="@tags" data-caption="Tags"></tr>
        </table>
    </div>
</script>   

With that created in a subsequent templates that exist within the CoveoResultList section. See how we reference the previous' template id value within the CoveoTemplateLoader's attribute data-template-id. This way, the above template will be loaded into this div for display in each template that references it. No more duplicating unecessary code and bloating your designs.


<script type='text/underscore' class='result-template' data-field-filetype='Image'>
    <div>
        <a class='CoveoResultLink'></a>
        <img class='CoveoThumbnail'></img>
        <div class='CoveoTemplateLoader' data-template-id='default-meta-template-table'></div>
    </div>
</script>

It's an extremely handy approach. Not only does it improve readability of the layout but it can potentially decrease the page size and improve page performance as a result.

How's Your Understanding Now?

So now that we've given you a taste of what's possible using and extending the CoveoResultList component; hopefully it gives you enough of a foundation when building your Result List that you start off on the right foot and save yourself a lot of time in the long run. Look forward to exploring other Coveo components in the future.

Image of Fishtank employee David Austin

David Austin

Development Team Lead | Sitecore Technology MVP x 3

David is a decorated Development Team Lead with Sitecore Technology MVP and Coveo MVP awards, as well as Sitecore CDP & Personalize Certified. He's worked in IT for 25 years; everything ranging from Developer to Business Analyst to Group Lead helping manage everything from Intranet and Internet sites to facility management and application support. David is a dedicated family man who loves to spend time with his girls. He's also an avid photographer and loves to explore new places.