SammyAttemptsCode's avatar

AIS refinement lists - and hiding them (Typesense adaptor)

Hi!

I am struggling with making my AIS refinement lists collapse for better UX. However I have not yet found a way to do so without AIS re-initializing and "forgetting" the selected facets (filters). I am struggling with finding a working solution and I have not found any examples that are applicable to me.

Below I have pasted a snippet of the code. I have a toggle, showColorFamily, which determines the state of the collapse. I can't mark the list items as Hidden or render only the selected refinements with Vue if the Show is false. AIS sees this as a change and wants to re-initialize.

Does anyone have a good, working example of how this gets done? That would ultimately help me the most.

Thanks in advance,

                <h3
                    class="text-sm font-medium my-2 px-3 text-dark-blue pb-1 border-b cursor-pointer select-none flex justify-between items-center"
                    @click="showColorFamily = !showColorFamily"
                >
                    <span>Color Family</span>
                    <span class="text-xs">
                        {{ showColorFamily ? '−' : '+' }}
                    </span>
                </h3>

                <div>
                    <ais-refinement-list
                        :class-names="{
                      'ais-RefinementList-list': 'flex flex-col gap-0',
                      'ais-RefinementList-item': 'flex items-center justify-between px-2 py-0.5',
                      'ais-RefinementList-label': 'flex items-center gap-2 w-full',
                      'ais-RefinementList-checkbox': 'w-4 h-4 accent-dark-blue',
                      'ais-RefinementList-labelText': 'truncate',
                      'ais-RefinementList-count': 'text-xs text-gray-500',
                      'ais-RefinementList-item--selected': 'font-semibold',
                      'ais-RefinementList-item--disabled': 'opacity-50 cursor-not-allowed'
                    }"
                        :limit="20"
                        :sort-by="['name:asc']"
                        attribute="color_family"
                    >
                        <template #item="{ item, refine }">
                            <li
                                :class="[
                              'flex items-center gap-2 px-2 py-0.5 rounded flex-1',
                              (item.isRefined)
                            ? 'font-semibold'
                            : ''
                            ]"
                            >
                                <!-- Image -->
                                <img
                                    :src="colorFamilyImages[item.value] ?? '/storage/images/icons/colors/placeholder.png'"
                                    alt=""
                                    class="w-8 h-8 object-contain"
                                />

                                <!-- Checkbox and name -->
                                <label class="flex items-center gap-2 cursor-pointer">
                                    <input
                                        :checked="item.isRefined"
                                        :disabled="item.isDisabled"
                                        class="w-4 h-4 accent-dark-blue"
                                        type="checkbox"
                                        @change="refine(item.value)"
                                    />
                                    <span class="truncate">{{ item.label }}</span>
                                </label>

                                <!-- Color Count -->
                                <span class="text-xs text-gray-500 ml-auto">{{ item.count }}</span>
                            </li>
                        </template>


                    </ais-refinement-list>
                </div>
0 likes
2 replies
LaryAI's avatar
Level 58

Here's a solid solution for collapsing an Algolia InstantSearch (AIS) refinement list in Vue without "resetting" the selected filters.

Problem Recap

  • Hiding or not rendering <ais-refinement-list> makes AIS forget user-selected filters.
  • We want to let users collapse (hide the choices) but keep their selected facets.

Solution Approach

Key Point:
Only hide the visible part (using CSS), never remove/ref destructure the component from the DOM (i.e., avoid v-if or v-show on <ais-refinement-list> directly).
This way, AIS keeps facet selections in its state.


Implementation Example

1. Always render <ais-refinement-list>.
2. Use CSS or Vue bindings to collapse the content area inside the refinement list.

Here's a sample approach (adjust for your setup as needed):

Key changes:

  • The <ais-refinement-list> is never removed.
  • The internal <ul>...</ul> is hidden via :style="{ display: showColorFamily ? '' : 'none' }" or you can do this via a CSS class.
  • You can keep the header, selected items, etc. always visible if you prefer.

Optional: Animate the Collapse

You can use Vue <transition> wrappers and CSS classes for a nice collapse animation, but always make sure the underlying <ais-refinement-list> stays mounted.


Summary

  • Never conditionally render the <ais-refinement-list> itself (v-if or v-show --> will break facet state).
  • Collapse only the visible DOM inside using regular Vue show/hide techniques on an inner element.
  • This keeps AIS state & selections "alive".

If you need help with animating or customizing the collapse further, let me know!

SammyAttemptsCode's avatar

For those stumbling upon this in the future, I have found the issue.

The culprit is the

:sort-by="['name:asc']"

That is within the ais-refinement-list. Remove it and it won't refresh and reset the refinements.

Please or to participate in this conversation.