Search code examples
javascriptvue.jsalgolia

Timing issue with Algolia and VueJs when customising the refinement list


I am using Algolia to build up a refinement list of filters, and I have customized the algolia instance to display facets with no matches: Algolia docs on displaying facets with no matches

The issue I am having is that in the mounted function in VueJs Algolia is building up the refinement list, and then doing some magic to build the Dom. I am having an issue where I am trying to append a CSS class to these elements in the same mounted function but the NodeList I am working on is constantly returning [] empty.

My solution is completely working when typing, and when using the refinement list, but its not working on page reload as the timing of things is out of sync.

  mounted() {
    this.searchClient
      .searchForFacetValues([
        {
          indexName: this.indexName,
          params: {
            facetName: this.brandAttribute,
            facetQuery: '',
            maxFacetHits: this.brandLimit,
          },
        },
      ])
      .then(([{ facetHits }]) => {
        this.initialFacets.push(
          ...facetHits.map(facet => ({
            ...facet,
            label: facet.value,
            value: facet.value,
            isRefined: false,
            count: 0,
          }))
        );
      });

      console.log(this.$el.querySelectorAll(".ais-RefinementList-list .ais-RefinementList-count"));  //Returns empty

      setTimeout(() => {
        console.log(this.$el.querySelectorAll(".ais-RefinementList-list .ais-RefinementList-count")); //Is populated
      }, 5000);
  },

I have set a timeout to prove this is a timing issue. Inside my timeout The nodelist is returning as expected, and I can add my CSS class, but how long do I wait? I don't believe this is a correct solution

I have tried all VueJs lifecycle hooks and in all the NodeList is returning null.

What I need is:

After the page has completly loaded, loop over my nodeList and Add CSS. The way I am doing this is:

document.querySelectorAll(".ais-RefinementList-list .ais-RefinementList-count").forEach(
        function(x) {

          if(x.innerHTML == 0) {
            x.parentElement.style.backgroundColor = "red"
          } else {
            x.parentElement.style.backgroundColor = "white"
          }
        }
      );

Working Solution: Working solution:

Page Refresh, timing issue: timing issue

Putting code in timeout:

setTimeout(() => {
        this.$el.querySelectorAll(".ais-RefinementList-list .ais-RefinementList-count").forEach(
          function(x) {

            if(x.innerHTML == 0) {
              x.parentElement.style.backgroundColor = "red"
            } else {
              x.parentElement.style.backgroundColor = "white"
            }
          }
        );
      }, 5000);

Gives this solution after 5 seconds: Working:

5 second delay


Solution

  • I was able to overcome this with the solution of customizing the UI: Algolia docs, customizing the UI

    I completly overwrote my Refinement list, and conditionally added the needed classes using the :style binding directive.

    <ais-refinement-list
      attribute="ParentPageTitle"
      :transformItems="transformItems"
    >
    
      <label 
        slot="item"
        slot-scope="{ item }"
        class="ais-RefinementList-label"
        :style="[item.count ? {'background-color' : 'white'} : {'background-color' : 'red'}]"
      >
        <input type="checkbox" class="ais-RefinementList-checkbox">
        <span class="ais-RefinementList-labelText">{{item.value}}</span>
      </label>
    </ais-refinement-list>
    

    CSS is now able to correctly style the component on runtime, and the timing issue has been resolved