Insights

Different Ways To Interact With Coveo Facets

Change The Way You Interact With Facets

You've by now seen the out-of-the-box Search UI. You've got a search bar on top, search results on the right below that, and then facets on the left. It works, nothing wrong with it.

In many cases, it's all that's needed. Add a splash of CSS here and there and that's what most search pages look like. Does it have to? No.

In fact, the interaction with the entire Search UI is flexible enough that you can make the entire page look and feel like a completely new experience if so desired.

Today, we're going to focus on facets. Specifically, how you can easily alter and interact with them to meet your needs.

Before We Begin

What will we cover here today? Glad you asked.

  • Altering facet values
  • Triggering the selection or deselection of facet values by interacting with other HTML elements
  • Resetting facets using JavaScript

It seems like a lot, but it isn't. Each section of what we're going to cover leads us to be able to use other HTML elements in ways that alter a search experience.

Facets

There are several facets that you can use in a Coveo Search UI. Some are new, some have been deprecated. There are two groupings of facets. You have your Dynamic facets which include:

  • DynamicFacet
  • DynamicFacetRange
  • DynamicHierarchialFacet

It's recommended that going forward you use these over the other type, the Regular facets. The reason being is they're much more flexible in the handling of the data provided to them. It depends on what you're trying to do. Regular facets include:

  • Facet
  • FacetRange
  • FacetSlider
  • TimespanRange
  • CategoryFacet
  • SimpleFilter

For a breakdown in greater detail, you can check out the Coveo Facet Types page.

Altering Facet Values

Pretty much any facet value can be displayed differently upon render. You don't need to do very much to make it happen.

Ideally, a facet's values would be updated to the desired values during the indexing process via a computed field calculation or through an Extension.

What if you have multiple search pages using the same source and each one needs to represent that data differently, then you likely will want to change that value in the UI.

Changing Values During Initialization

Let's say, your facets consisted of a list of country codes. i.e. US, JP, CA, etc. For the end-user, not very handy, so let's rename them to United States, Australia, Canada.

You'd want this to happen as part of the initialization process of the search page.


<div class="CoveoDynamicFacet" id="countryFacet" data-title="Country" data-field="@countrycode"></div>

With the facet in place, we can interact with change the facet values in two ways.

Using The data-value-caption Attribute

By adding the relationship directly to the facet itself, shown below we can update the values. This is often handy when implementing using Hive.


<div class="CoveoDynamicFacet" id="countryFacet" data-title="Country" data-field="@countrycode" data-value-caption='{ "US": "United States", "JP": "Japan", "CA": "Canada" }' ></div>
    

Using Init / Option Actions


Coveo.init(document.getElementById("search"),{
countryFacet {
    valueCaption: {
        "US": "United States",
        "JP": "Japan",
        "CA": "Canada"
    }
}
});

This short bit of code links the new facet values based upon the id attribute of the facet. Super simple. Now we know we can interact with facets to alter the values, what about interacting with them to trigger the selection or deselection of said values.

Triggering Facet Selection Or Deselection

What if we have a client that wants to be able to use facets but doesn't want to see facets in their native look & feel. Maybe they want to use a couple of buttons.

It's important to note that even after changing the values for the captions above, we're still going to be interacting with them using their original value.

The original value is actually maintained in the HTML, within the hierarchy as shown below:


<span class="coveo-facet-value-caption" title="United States" data-original-value="US">United States</span>

Setting Up A Button

This should be fairly obvious but I'm setting up a simple button that, upon clicking, will trigger the associated facet value to be selected or deselected.


<button class="facet-selection" data-facet-id="countryFacet" data-facet-value="US">United States</button>

Setting Up The Event

When it comes to setting up the event it's important to know when to initialize the click event. You can't just enable it at any time.

When is the right time, you ask? You want to be sure to set up your click events when the afterInitialization Coveo pipeline event has triggered. The facet needs to have been initialized before otherwise clicking a button can result in nothing happening.

More importantly though, right before the afterInitialization event is triggered, the state from the hash portion of the URL is applied (i.e. facet values that should be selected are updated to show are selected).

As such this is also a good trigger point to apply button state, if you want certain buttons to show they've been selected to match the state of the facet.

Important Methods Of Note

There are three facet methods one should know when it comes to changing a facet value.

  • toggleSelectValue - Toggles the value on or off depending on state
  • selectValue - Toggles facet value on
  • deselectValue - Toggles facet value off

None of the methods above will cause a search query to be executed. You have to perform that action separately.

Let's take a look at an example.


Coveo.$$(document.getElementById("search")).on('afterInitialization', function() {
$(".facet-selection").click(function(el) {
    
    // Get the facet for the button and then the DOM element 
    var facetId = $(el.target).data('facet-id');
    var facetElement = document.getElementById(facetId);

    // Get the facet value to look for
    var toggleFacetValue = $(el.target).data('facet-value');

    // Get the facet instance and toggle the value
    var facetInstance = Coveo.get(facetElement);
    facetInstance.toggleSelectValue(toggleFacetValue);

    // After the value has been selected or deselected it's important to execute the 
    // query, otherwise it won't impact the search results.
    Coveo.executeQuery(document.getElementById("search"));
});
});

I want to call out a couple things about the above code.

  1. The state of the button. If you want to change the state of the button depending on the state of the facet (e.g. added a class or removing a class depending on if the facet has been selected or deselected) then you need to do additional work.
  2. When to display the button. If the search page isn't yet visible, you won't want to display the button. If the facet isn't ready to be clicked, the button should not be ready either. Forgetting to do so may result in your button being selected and the facet not being selected.

One way to get around that is by not using toggleSelectValue but rather a combination of selectValue and deselectValue as shown below in this modified version.

If toggleSelectValue returned the state rather than just returning void we could avoid this, but that's the way it is today.

I've expanded the stages so it's clearer as to what's happening where, as such you can likely do the same in far fewer steps.


Coveo.$$(document.getElementById("search")).on('afterInitialization', function() {
$(".facet-selection").click(function(e) {
    // Determine button state
    var isSelected = false;

    if ($(e.target).hasClass('selected')) {
        isSelected = true;
    }

    // Get the facet for the button and then the DOM element 
    var facetId = $(el.target).data('facet-id');
    var facetElement = document.getElementById(facetId);

    // Get the facet value to look for
    var toggleFacetValue = $(el.target).data('facet-value');

    // Get the facet instance and then depending on button state select or deselect
    var facetInstance = Coveo.get(facetElement);

    if (isSelected) {
        facetInstance.deselectValue(toggleValue);
        $(e.target).removeClass('selected');
    } else {
        facetInstance.selectValue(toggleValue);
        $(e.target).addClass('selected');
    }

    // After the value has been selected or deselected it's important to execute the 
    // query, otherwise it won't impact the search results.
    Coveo.executeQuery(document.getElementById("search"));
});
});

Resetting Facets Values

Just as important as knowing how to toggle whether a facet value is selected or not is the ability to reset a single facet or all facets.

If you have a lot of values, perhaps you want to create a simple yet obvious button for resetting everything back to the original state.

Reset All Facets On Button Click

Much the same way as toggling facet value selection, we can reset them all back to the default state. Let's say we have a button, shown below, that we want to reset all facets.


<button class="facet-reset" >Reset Everything</button>

How do we make it actually reset everything? Well, if we're using the Dynamic Facet for all facets, we could do something as simple as the following.

If we have other facet types, we can simply add other selections and 'reset' them as well.


Coveo.$$(document.getElementById("search")).on('afterInitialization', function() {
$(".facet-reset").click(function(e) {
    // Set the facets back to default state
    $('.CoveoDynamicFacet').coveo('reset');

    // Execute the query to get the appropriate search results.
    Coveo.executeQuery(document.getElementById("search"));
});
});

What Else Can You Do?

Honestly, you're only limited by your imagination. I just wanted to present a few simple ways of interacting with facets that will, at the very least, lay a groundwork for you to build upon.

Hey, Developers!

We're on the look out for talented developers to join our team.

Think you have what it takes?

Meet David Austin

Development Team Lead

📷🕹️👪

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.

Connect with David