API Reference / Vue InstantSearch Widgets / ais-menu
Aug. 23, 2019
Widget signature
<ais-menu
  attribute="string"
  // Optional parameters
  :limit="number"
  :show-more="boolean"
  :show-more-limit="number"
  :sort-by="string[]|function"
  :transform-items="function"
  :class-names="object"
/>

About this widget

The ais-menu widget displays a menu that lets the user choose a single value for a specific attribute.

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 attribute="categories" />

Props

attribute
type: string
Required

The name of the attribute in the record.

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

The maximum amount of values to show (when not showing more).

1
2
3
4
<ais-menu
  [...]
  :limit="20"
/>
show-more
type: boolean
default: false
Optional

Whether to display a button that expands the number of items.

1
2
3
4
<ais-menu
  [...]
  show-more
/>
show-more-limit
type: number
default: 20
Optional

Amount of items to show if showing more. Requires show-more to be true.

1
2
3
4
<ais-menu
  [...]
  :show-more-limit="30"
/>
sort-by
type: string[]|function
default: ["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.

1
2
3
4
<ais-menu
  [...]
  :sort-by="['isRefined', 'count:desc']"
/>
transform-items
type: function
default: x => x
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
18
19
20
<template>
  <!-- ... -->
  <ais-menu
    [...]
    :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-Menu: the root element of the widget.
  • .ais-Menu--noRefinement: the root element of the widget with no refinement.
  • .ais-Menu-list: the list of all menu items.
  • .ais-Menu-item: the menu list item.
  • .ais-Menu-item--selected: the selected menu list item.
  • .ais-Menu-link: the clickable menu element.
  • .ais-Menu-label: the label of each item.
  • .ais-Menu-count: the count of values for each item.
  • .ais-Menu-showMore: the button used to display more categories.
  • .ais-Menu-showMore--disabled: the disabled button used to display more categories.
1
2
3
4
5
6
7
8
<ais-menu
  [...]
  :class-names="{
    'ais-Menu': 'MyCustomMenu',
    'ais-Menu-link': 'MyCustomMenuLink',
    // ...
  }"
/>

Customize the UI

default

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

Scope

  • items: object[]: the values applicable to this menu.
  • canRefine: boolean: whether or not the refinement can be applied.
  • canToggleShowMore: boolean: whether or not show-more is possible.
  • isShowingMore: boolean: whether or not show-more is enabled.
  • refine: (value: string) =\> void: a function to select a refinement.
  • createURL: (item: object) =\> string: a function to return a link for this refinement.

Where each item is an object containing:

  • value: string: the value of the menu item.
  • label: string: the human-readable value of the menu item.
  • count: number: the 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
19
20
21
22
23
24
25
26
27
<ais-menu attribute="categories">
  <ul
    slot-scope="{
      items,
      canToggleShowMore,
      isShowingMore,
      toggleShowMore,
      refine,
      createURL,
    }"
  >
    <li v-for="item in items" :key="item.value">
      <a
        :href="createURL(item.value)"
        :style="{ fontWeight: item.isRefined ? 'bold': '' }"
        @click.prevent="refine(item.value)"
      >
        {{item.label}} - {{item.count}}
      </a>
    </li>
    <li>
      <button :disabled="!canToggleShowMore" @click="toggleShowMore">
        {{ isShowingMore ? 'Less' : 'More'}}
      </button>
    </li>
  </ul>
</ais-menu>
showMoreLabel

The slot to override the DOM output for the label of the “Show more” button.

Scope

  • isShowingMore: boolean: whether or not show-more is enabled.
1
2
3
4
5
<ais-menu attribute="categories" show-more>
  <span slot="showMoreLabel" slot-scope="{ isShowingMore }">
    {{ isShowingMore ? 'Less' : 'More' }}
  </span>
</ais-menu>

HTML output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="ais-Menu">
  <ul>
    <li>
      <a class="ais-Menu-link">
        <span class="ais-Menu-label">Apple</span>
        <span class="ais-Menu-count">50</span>
      </a>
    </li>
    <!-- more items -->
  </ul>
  <button class="ais-Menu-showMore">
    Show more
  </button>
</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?