> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Show and hide widgets

> Learn how you can prevent common issues when showing and hiding Vue InstantSearch widgets.

export const SearchRequest = () => <Tooltip tip="A search request is a single HTTP call to the Algolia Search API that can run one or more search operations. It can include multiple queries, for example, when querying several indices at once.">
    search request
  </Tooltip>;

Widgets do more than display a UI—they each interact with a piece of the [`uiState`](/doc/api-reference/widgets/ui-state/vue) that maps to one or more Algolia search parameters.

For example, the [`ais-search-box`](/doc/api-reference/widgets/search-box/vue) controls the [`query`](/doc/api-reference/api-parameters/query), the [`ais-refinement-list`](/doc/api-reference/widgets/refinement-list/vue) interacts with [`facetFilters`](/doc/api-reference/api-parameters/facetFilters), parameter.

**When a widget is mounted or unmounted, this is reflected in the InstantSearch UI state and included in the <SearchRequest />.**

Consider what happens in a mobile search interface with filters ([`ais-refinement-list`](/doc/api-reference/widgets/refinement-list/vue)): when a user clicks the **Filters** button, a dialog opens and displays the refinements.

<video controls>
  <source src="https://mintcdn.com/algolia/i8QBUoaIRr-QIxRo/videos/filters-dialog.webm?fit=max&auto=format&n=i8QBUoaIRr-QIxRo&q=85&s=0efbd3b1f13e3a5c4b6b4a9348f9c6a1" type="video/webm" data-path="videos/filters-dialog.webm" />

  <source src="https://mintcdn.com/algolia/i8QBUoaIRr-QIxRo/videos/filters-dialog.mp4?fit=max&auto=format&n=i8QBUoaIRr-QIxRo&q=85&s=212c19b55a23178d0b54fbbf6e896a33" type="video/mp4" data-path="videos/filters-dialog.mp4" />
</video>

In many component libraries, the `Dialog` component mounts and unmounts its content when toggled.
**This is problematic when used with InstantSearch components.**

For example, if you have a [`ais-refinement-list`](/doc/api-reference/widgets/refinement-list/vue) widget nested in the dialog:

* The widget wouldn't be mounted on the first app load because the dialog box is closed.
* When the dialog box opens, the widget mounts, adding it to the InstantSearch state and triggering a new request, even before a refinement has been selected.
* When the dialog box closes, the widget unmounts, removing it from the InstantSearch state and losing all selected refinements.

To keep the state available after unmount, you can either:

* [Enable `preserveSharedStateOnUnmount`](#enable-preservesharedstateonunmount)
* [Keep the widget mounted but hidden](#keep-the-widget-mounted-but-hidden)

## Enable `preserveSharedStateOnUnmount`

Enabling [`preserveSharedStateOnUnmount`](/doc/api-reference/widgets/instantsearch/vue#param-future-preserve-shared-state-on-unmount) prevents a widget's state from being cleared when it's unmounted, as long as other widgets share the same refinements.
Enabling this option changes how `dispose` is used in the InstantSearch lifecycle.

By default when a widget is removed, it provides a cleared version of the state that will be propagated throughout the other widgets.

```html theme={"system"}
<template>
  <ais-instant-search
    :future="{ preserveSharedStateOnUnmount: true }"
    :search-client="searchClient"
    index-name="instant_search"
  >
    <Search />
    <button type="button" @click="showMenu != showMenu">Filters</button>
    <virtual-refinement-list attribute="brand" />
    <ais-refinement-list v-if="showMenu" attribute="brand" />
  </ais-instant-search>
</template>

<script>
import { liteClient as algoliasearch } from 'algoliasearch/lite';
import { connectRefinementList } from 'instantsearch.js/es/connectors';
import { AisInstantSearch, AisRefinementList, createWidgetMixin } from 'vue-instantsearch';

const appID = "ALGOLIA_APPLICATION_ID";
const apiKey = "ALGOLIA_SEARCH_API_KEY";

const searchClient = algoliasearch(appID, apiKey);

const VirtualRefinementList = {
  name: 'VirtualRefinementList',
  mixins: [createWidgetMixin({
    connector: connectRefinementList,
  })]
  render() {
    return null;
  }
}

export default {
  components: {
    AisInstantSearch,
    AisRefinementList,
    VirtualRefinementList,
  },
  data() {
    return {
      searchClient,
      showMenu: true,
    };
  },
};
</script>
```

<Note>
  This option is available from v4.11.0 and **will be the only option from Vue InstantSearch v5**.
</Note>

## Keep the widget mounted but hidden

The most straightforward way to retain a widget's state and refinements is to **avoid unmounting it**.

You can, for example, hide the content of the dialog with CSS:

```html theme={"system"}
<template>
  <ais-instant-search
    :future="{ preserveSharedStateOnUnmount: true }"
    :search-client="searchClient"
    index-name="instant_search"
  >
    <Search />
    <button type="button" @click="showMenu != showMenu">Filters</button>
    <ais-refinement-list v-show="showMenu" attribute="brand" />
  </ais-instant-search>
</template>

<script>
import { liteClient as algoliasearch } from 'algoliasearch/lite';
import { AisInstantSearch, AisRefinementList } from 'vue-instantsearch';

const appID = "ALGOLIA_APPLICATION_ID";
const apiKey = "ALGOLIA_SEARCH_API_KEY";

const searchClient = algoliasearch(appID, apiKey);

export default {
  components: {
    AisInstantSearch,
    AisRefinementList,
  },
  data() {
    return {
      searchClient,
      showMenu: true,
    };
  },
};
</script>
```

If you're using a component library,
you can verify whether the dialog component lets you avoid unmounting its content.
For example, the [`<Dialog>` component from Headless UI](https://headlessui.com/v1/vue/dialog) lets you turn off unmounting with the `unmount` option.
