API Reference / Vue InstantSearch / ais-menu-select
Signature
<ais-menu-select
  attribute="string"
  // Optional parameters
  :limit="number"
  :sort-by="string[]|function"
  :transform-items="function"
  :class-names="object"
/>

About this widget

The ais-menu-select widget allows a user to select a single value to refine inside a select element.

Requirements

The attribute passed to the attribute prop must be added in attributes for faceting, either on the dashboard or using attributesForFaceting with the API.

Examples

1
<ais-menu-select attribute="categories" />

Props

attribute
type: string
Required

The name of the attribute in the record.

1
<ais-menu-select attribute="categories" />
limit
type: number
default: 10
Optional

The maximum number of values to display.

1
2
3
4
<ais-menu-select
  [...]
  :limit="20"
/>
sort-by
type: string[]|function
default: Uses facetOrdering if set, ["name:asc", "count:desc"]

How to sort refinements. Must be one or more of the following strings:

  • "count:asc"
  • "count:desc"
  • "name:asc"
  • "name:desc"
  • "isRefined"

It’s also possible to give a function, which receives items two by two, like JavaScript’s Array.sort.

If facetOrdering is set for this facet in renderingContent, and no value for sortBy is passed to this widget, facetOrdering is used, and the default order as a fallback.

When using an array, take steps to avoid creating infinite loops. When you use an array as a prop, it causes the widget to re-register on every render, and this can sometimes cause these infinite loops.

1
<ais-menu-select :sort-by="['isRefined', 'count:desc']" />
transform-items
type: function
default: items => items
Optional

Receives the items, and is called before displaying them. Should return a new array with the same shape as the original array. Useful for mapping over the items to transform, and remove or reorder them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
  <!-- ... -->
  <ais-menu-select :transform-items="transformItems" />
</template>

<script>
  export default {
    methods: {
      transformItems(items) {
        return items.map(item => ({
          ...item,
          label: item.label.toUpperCase(),
        }));
      },
    },
  };
</script>
class-names
type: object
default: {}
Optional

The CSS classes to override.

  • .ais-MenuSelect: the root element of the widget
  • .ais-MenuSelect--noRefinement: the root element of the widget with no refinement
  • .ais-MenuSelect-select: theselect element
  • .ais-MenuSelect-option: the option elements of the select
1
2
3
4
5
6
7
8
<ais-menu-select
  [...]
  :class-names="{
    'ais-MenuSelect': 'MyCustomMenuSelect',
    'ais-MenuSelect-option': 'MyCustomMenuSelectOption',
    // ...
  }"
/>

Customize the UI

default

The slot to override the complete DOM output of the widget.

Note that when you implement this slot, none of the other slots will change the output, as the default slot surrounds them.

Scope

  • items: object[]: the values applicable to this menu.
  • canRefine: boolean: can the refinement be applied?
  • refine: (value: string) => void: a function to select a refinement.
  • createURL: (item: string) => string: a function to return a link for this refinement.
  • sendEvent: (eventType: 'click', facetValue: string) => void: the function to send click events.
    • The view event is automatically sent when the facets are rendered.
    • The click event is automatically sent when refine is called.
    • You can learn more about the insights middleware.

Where each item is an object containing:

  • value: string: The value of the menu item.
  • label: string: Human-readable value of the menu item.
  • count: number: Number of results matched after a refinement is applied.
  • isRefined: boolean: indicates if the refinement is applied.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<ais-menu-select attribute="categories">
  <template v-slot="{ items, canRefine, refine, sendEvent }">
    <select
      :disabled="!canRefine"
      @change="refine($event.currentTarget.value)"
    >
      <option value="">All</option>
      <option
        v-for="item in items"
        :key="item.value"
        :value="item.value"
        :selected="item.isRefined"
      >
        {{ item.label }}
      </option>
    </select>
  </template>
</ais-menu-select>
item

The slot to override the content of an option element. Make sure to use template as the root, since any other elements inside an option are not allowed.

Scope

  • item: object: the values applicable to the option.

Where item is an object containing:

  • value: string: The value of the menu item.
  • label: string: Human-readable value of the menu item.
  • count: number: Number of results matched after a refinement is applied.
  • isRefined: boolean: indicates if the refinement is applied.
1
2
3
4
5
<ais-menu-select attribute="categories">
  <template v-slot:item="{ item }">
    {{ item.label }}
  </template>
</ais-menu-select>
defaultOption

The slot to override the content of the option element which selects “all items”. Make sure to use template as the root, since any other elements inside an option are not allowed.

Scope

No scope is provided to this slot.

1
2
3
4
5
<ais-menu-select attribute="categories">
  <template v-slot:defaultOption>
    See all categories
  </template>
</ais-menu-select>

HTML output

1
2
3
4
5
6
7
8
<div class="ais-MenuSelect">
  <select class="ais-MenuSelect-select">
    <option class="ais-Menu-option">
      Apple (50)
    </option>
    <!-- more items -->
  </select>
</div>

If SEO is critical to your search page, your custom HTML markup needs to be parsable:

  • use plain <a> tags with href attributes for search engines bots to follow them,
  • use semantic markup with structured data when relevant, and test it.

Refer to our SEO checklist for building SEO-ready search experiences.

Did you find this page helpful?