Select refinementList facets programatically on page load

Hi there,
I can’t figure out how to achieve the logic below.

My website has 2 different refinementList javascript widgets that load different attributes (food and drinks). Everything works well when toggling the checkboxes manually.

The website has 3 different main navigation links (“View Our Shop”, “Shop Food” and “Shop Drinks”). The link “View Our Shop” redirects to /shop and it works as expected with the current logic. So all products are shown by default and then users can manually filter by clicking on the faceted search.

What I would like to achieve is the functionality for the other 2 links “Shop Food” and “Shop Drinks” that will redirect to /shop/food and /shop/drinks respectively. So when a user clicks on “Shop Food”, I would like to automatically select all the food categories so only food items are displayed, and the same for “Shop Drinks” where only the drinks products will get displayed when the user access the /shop/drinks url. Then if the user wants to clear the refinements and view food items, they will be able to do that manually.

Currently my code looks something like this:

refinementList({
  container: '#refinementsFood',
  attribute: 'productCategoriesFood',
  operator: 'or',
  templates: {

  }
}),
refinementList({
  container: '#refinementsDrinks',
  attribute: 'productCategoriesDrinks',
  operator: 'or',
  templates: {
  }
}),
clearRefinements({
  container: '#clearRefinementsFood',
  includedAttributes: ['productCategoriesFood'],
  templates: {
    resetLabel: 'Clear all',
  },
}),
clearRefinements({
  container: '#clearRefinementsDrinks',
  includedAttributes: ['productCategoriesDrinks'],
  templates: {
    resetLabel: 'Clear all',
  },
}),

Could you please point me towards the right direction here? I’ve tried doing it in js so I manually check all the checkboxes in javascript but although they appear as checked, the hits results are not filtered. Please see below.

.on('render', function() {
let facetedFood = document.getElementById("refinementsFood");
  let foodCheckboxes = facetedFood.getElementsByClassName('ais-RefinementList-checkbox');
  for (let i=0;i<foodCheckboxes.length;i++) {
    foodCheckboxes[i].checked = true;
  }
});

Cheers,
Alby

As you’ve realized, those refinementList values are not meant to be interacted with programatically.
Manipulating the state of the instantsearch instance is done using its helper instance, which is accessible with search.helper:

var search = instantsearch(/* ... */);
search.on('render', () => {
  console.log(search.helper.getPage());
});

The same helper can also be accessed using the searchFunction parameter, which allows to manipulate it before a search is launched instead of after:

var search = instantsearch({
  /* ... */
  searchFunction: (helper) => {
    console.log(search.helper.getPage());
    helper.search();
  }
});

To set a facet value for a facet using the or operator (also called “disjunctive facet”), you’d need to use addDisjunctiveFacetRefinement, as described here:
https://community.algolia.com/algoliasearch-helper-js/reference.html#disjunctive-facets
Note: when using this method, the current search page gets reset to 0. If you use it, backup the page using helper.getPage(), set the new facet refinement, and restore the page using setPage(page).

However, this “reactive approach”, which requires 2 back and forths: one to retrieve the list of facets and one to set them is not something I would recommend.
It has multiple issues:

  1. It requires 2 requests, which means the result list will be slower to arrive, requires more data transfer, and will likely flicker between both renders, first displaying everything, then displaying only what’s needed.
  2. You’re constrained by the limit parameter of the refinementList: by default it means you can only have 10 different types of foods and 10 different types of wines. Bumping it is possible, but there’s a hard limit at 1000. Also the more you request, the slower it gets because there’s more data to transmit and render.

An alternative would be to add an extra attribute to your records: category which could have 2 values: "food" or "wine".
You could then have an additional refinementList in your search to select which category you’re interested in.
Selecting one category would require a single filter, that you could set before the first search.

You could then reuse your search logic but change initialUiState to add a filter on the correct category.

Thanks for your reply @Jerska , somehow I didn’t get a notification and I didn’t see it until now.

I didn’t think about the extra category and it looks like a better solution at this stage but I need to give it a go first and will let you know.

Cheers,
Alby