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

# ais-numeric-menu

> Shows a list of numeric filters for refining search results.

```vue Signature theme={"system"}
<ais-numeric-menu
  attribute="string"
  :items="object[]"
  // Optional parameters
  :transform-items="function"
  :class-names="object"
/>
```

## Import

<Tabs>
  <Tab title="Component">
    To ensure optimal bundle sizes,
    see [Optimize build size](/doc/guides/building-search-ui/going-further/improve-performance/vue#optimize-build-size).

    ```js Vue icon=code theme={"system"}
    import { AisNumericMenu } from "vue-instantsearch";
    // Use "vue-instantsearch/vue3/es" for Vue 3

    export default {
      components: {
        AisNumericMenu
      },
      // ...
    };
    ```
  </Tab>

  <Tab title="Plugin">
    This imports all widgets, even the ones you don't use.
    For more information, see [Get started with Vue InstantSearch](/doc/guides/building-search-ui/getting-started/vue).

    ```js JavaScript icon="code" theme={"system"}
    import Vue from "vue";
    import InstantSearch from "vue-instantsearch";
    // Use "vue-instantsearch/vue3/es" for Vue 3

    Vue.use(InstantSearch);
    ```
  </Tab>
</Tabs>

<Card title="See this widget in action" icon="monitor-play" href="https://instantsearchjs.netlify.app/stories/vue/?selectedKind=ais-numeric-menu" horizontal>
  Preview this widget and its behavior.
</Card>

## About this widget

The `ais-numeric-menu` widget displays a list of numeric filters in a list.
Those numeric filters are pre-configured when creating the widget.

### Requirements

The values of the attribute must be numbers, not strings.

## Examples

```vue Vue icon=code theme={"system"}
<ais-numeric-menu
  attribute="price"
  :items="[
    { label: 'All' },
    { label: '<= 10$', end: 10 },
    { label: '10$ - 100$', start: 10, end: 100 },
    { label: '100$ - 500$', start: 100, end: 500 },
    { label: '>= 500$', start: 500 },
  ]"
/>
```

## Props

<ParamField body="attribute" type="string" required>
  The name of the attribute in the record.

  ```vue Vue icon=code theme={"system"}
  <ais-numeric-menu
    [...]
    attribute="price"
  />
  ```
</ParamField>

<ParamField body="items" type="object[]" required>
  A list of all the options to display, with:

  * `label: string`. Label of the option
  * `start: number`. The option must be greater than or equal to `start` (lower bound).
  * `end: number`. The option must be smaller than or equal to `end` (upper bound).

  ```vue Vue icon=code theme={"system"}
  <ais-numeric-menu
    [...]
    :items="[
      { label: 'All' },
      { label: '<= 10$', end: 10 },
      { label: '10$ - 100$', start: 10, end: 100 },
      { label: '100$ - 500$', start: 100, end: 500 },
      { label: '>= 500$', start: 500 },
    ]"
  />
  ```
</ParamField>

<ParamField body="transform-items" type="function" default="items => items">
  A function that receives the list of items before they are displayed.
  It should return a new array with the same structure.
  Use this to transform, filter, or reorder the items.

  The function also has access to the full `results` data,
  including all standard [response parameters](/doc/guides/building-search-ui/going-further/backend-search/in-depth/understanding-the-api-response/)
  and [parameters from the helper](https://community.algolia.com/algoliasearch-helper-js/reference.html#query-parameters),
  such as `disjunctiveFacetsRefinements`.

  ```vue Vue icon=code theme={"system"}
  <template>
    <!-- ... -->
    <ais-numeric-menu
      [...]
      :transform-items="transformItems"
    />
  </template>

  <script>
  export default {
    methods: {
      transformItems(items) {
        return items.map((item) => ({
          ...item,
          label: item.label.toUpperCase(),
        }));
      },

      /* or, combined with results */
      transformItems(items, { results }) {
        return items.map((item) => ({
          ...item,
          label:
            item.isRefined && results
              ? `${item.label} (${results.nbHits} hits)`
              : item.label,
        }));
      },
    },
  };
  </script>
  ```
</ParamField>

<ParamField body="class-names" type="object" default="{}">
  The [CSS classes you can override](/doc/guides/building-search-ui/widgets/customize-an-existing-widget/vue#style-your-widgets):

  * `ais-NumericMenu`. The root element of the widget.
  * `ais-NumericMenu--noRefinement`. The root element of the widget without refinement.
  * `ais-NumericMenu-list`. The ranges list.
  * `ais-NumericMenu-item`. The ranges list item.
  * `ais-NumericMenu-item--selected`. The ranges list selected item.
  * `ais-NumericMenu-label`. The label of each item.
  * `ais-NumericMenu-radio`. The radio of each item.
  * `ais-NumericMenu-labelText`. The text of each item.

  ```vue Vue icon=code theme={"system"}
  <ais-numeric-menu
    [...]
    :class-names="{
      'ais-NumericMenu': 'MyCustomNumericMenu',
      'ais-NumericMenu-list': 'MyCustomNumericMenuList',
      // ...
    }"
  />
  ```
</ParamField>

## Customize the UI

<ParamField body="default">
  The slot to override the complete DOM output of the widget.

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

  **Scope**

  * `items: object[]`. The list of items the widget can display.
  * `canRefine: boolean`. Whether a refinement can be applied.
  * `refine: (value: string) => void`. The function to call with the next value of the refinement.
  * `createURL: (value: string) => void`. The function to generate a URL for the provided 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.

    To learn more, see the [`insights`](/doc/api-reference/widgets/insights/vue) middleware.

  With each item an `object` with:

  * `label: string`. The label for the option.
  * `value: string`. The encoded URL of the bounds object with a `{start, end}` form. This value can be used verbatim in the webpage and can be read by `refine` directly. If you want to inspect the value, you can do `JSON.parse(window.decodeURI(value))` to get the object.
  * `isRefined: boolean`. Whether the refinement is selected.

  ```vue Vue icon=code theme={"system"}
  <ais-numeric-menu
    attribute="price"
    :items="[
      { label: 'All' },
      { label: '<= 10$', end: 10 },
      { label: '10$ - 100$', start: 10, end: 100 },
      { label: '100$ - 500$', start: 100, end: 500 },
      { label: '>= 500$', start: 500 },
    ]"
  >
    <template v-slot="{ items, refine, createURL, sendEvent }">
      <ul>
        <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 }}
          </a>
        </li>
      </ul>
    </template>
  </ais-numeric-menu>
  ```
</ParamField>

## HTML output

```html HTML icon=code-xml theme={"system"}
<div class="ais-NumericMenu">
  <ul class="ais-NumericMenu-list">
    <li class="ais-NumericMenu-item ais-NumericMenu-item--selected">
      <label class="ais-NumericMenu-label">
        <input
          class="ais-NumericMenu-radio"
          type="radio"
          name="NumericMenu"
          checked
        />
        <span class="ais-NumericMenu-labelText">All</span>
      </label>
    </li>
    <li class="ais-NumericMenu-item">
      <label class="ais-NumericMenu-label">
        <input class="ais-NumericMenu-radio" type="radio" name="NumericMenu" />
        <span class="ais-NumericMenu-labelText">Less than 500</span>
      </label>
    </li>
  </ul>
</div>
```
