Skip to content

Multi Select

The VMultiSelect component is a customizable multiselect dropdown for Vue. It allows users to select multiple items from a list and displays the selected items in the form of badges.

Usage

Basic Usage

To use the VMultiSelect component, just use it in the template.

INFO

The VMultiSelect component is registered globally when you install with @morpheme/ui. So you don't need to import it manually.

Clearable

To enable the clearable feature, which allows users to clear their selections, add the clearable prop to the VMultiSelect component.

Max Badge

To limit the number of badges displayed, you can use the max-badge prop. This prop specifies the maximum number of badges that will be displayed before a "and X more" badge is shown.

Label

You can add a label to the VMultiSelect component by using the label prop.

Custom Style

You can customize the style of the VMultiSelect component using various props.

Initial Errors

You can display initial errors for the VMultiSelect component by using the initialErrors prop in the useForm hook.

Custom Compare Function

You can use a custom compare function for the search feature of the VMultiSelect component by using the search-by prop.

Props

NameTypeDefault
itemsArray as PropType<VMultiSelectItem[]>[]
itemTextstring'text'
itemValuestringvalue
searchBystring''
placeholderstring'Search...'
namestring''
errorbooleanfalse
errorMessagesArray'[]'
clearableboolean'false'
disabledboolean'false'
readonlyboolean'false'
maxBadgenumber0
delaynumber'500'
idstring''
inputPropsObject as PropType<Record<string, any>>'{}'
selectAllbooleanfalse
loadingbooleanfalse
wrapperClassstring''
inputClassstring''
badgeColorstring'primary'
badgeClassstring''
badgePropsobject{}
dropdownClassstring''
itemClassstring''
checkWrapperClassstring''
checkIconClassstring''
noDataClassstring''
loadingClassstring''
labelstring''
labelClassstring'mb-2 block'
rulesstring''
errorClassstring'text-error-600 mt-1 text-sm'
transitionstring'fade'
hintString''
hideErrorBooleanfalse

Events

click:outside

This event is emitted when the user clicks outside of the VMultiSelect component. It can be useful for closing the dropdown menu when the user clicks outside of it.

vue
<template>
  <VMultiSelect @click:outside="closeDropdown" />
</template>

<script>
export default {
  methods: {
    closeDropdown() {
      // Close the dropdown menu
    },
  },
};
</script>
<template>
  <VMultiSelect @click:outside="closeDropdown" />
</template>

<script>
export default {
  methods: {
    closeDropdown() {
      // Close the dropdown menu
    },
  },
};
</script>

update:modelValue

This event is emitted when the selected values of the VMultiSelect component are updated. It is emitted with an array of the selected values.

vue
<template>
  <VMultiSelect @update:modelValue="updateSelectedValues" />
</template>

<script>
export default {
  methods: {
    updateSelectedValues(values) {
      // values is an array of the selected values
    },
  },
};
</script>
<template>
  <VMultiSelect @update:modelValue="updateSelectedValues" />
</template>

<script>
export default {
  methods: {
    updateSelectedValues(values) {
      // values is an array of the selected values
    },
  },
};
</script>

This event is emitted when the user performs a search in the VMultiSelect component. It is emitted with the search query string.

vue
<template>
  <VMultiSelect @search="searchItems" />
</template>

<script>
export default {
  methods: {
    searchItems(query) {
      // query is the search query string
    },
  },
};
</script>
<template>
  <VMultiSelect @search="searchItems" />
</template>

<script>
export default {
  methods: {
    searchItems(query) {
      // query is the search query string
    },
  },
};
</script>

selected

This event is emitted when the user selects an item from the VMultiSelect component. It is emitted with the selected item.

vue
<template>
  <VMultiSelect @selected="itemSelected" />
</template>

<script>
export default {
  methods: {
    itemSelected(item) {
      // item is the selected item
    },
  },
};
</script>
<template>
  <VMultiSelect @selected="itemSelected" />
</template>

<script>
export default {
  methods: {
    itemSelected(item) {
      // item is the selected item
    },
  },
};
</script>

Slots

selection

Allow customized selection rendering. Will only be run when there is selected value. If maxBadge is set to valid value, it will only be run for items within the set limit.

Slot Props

PropValueDescription
indexnumberIndex of the current selection
itemanyCurrent selected item at given index
valuestringLabel of selected item.
onRemovefunctionCallback to remove selected item

max-selection

Allows customized rendering for max-selection rendering. This will only be run if maxBadge props is set to valid value.

Slot Props

PropValueDescription
lengthnumberNumber of selected items being hidden

select-all

Allows custom render for select all option. This will only be run if selectAll props is set to valid value.

Slot Props

PropValueDescription
iSelectedbooleanA flag to indicate if all options is currently selected
onClickfunctionCallback to toggle select all state

prepend.item

Add custom element before option list

append.item

Add custom element after option list

item.label

Allows custom render for option item.

Slot Props

PropValueDescription
indexnumberIndex of the current selection
itemanyCurrent selected item at given index
valuestringLabel of selected item.
iSelectedbooleanA flag to indicate if it is currently selected

CSS Variables

scss
:root {
  --v-multi-select-border-color: var(--v-input-border-color);
  --v-multi-select-border-radius: var(--v-input-border-radius);
  --v-multi-select-bg-color: var(--v-input-bg-color);
  --v-multi-select-text-color: var(--color-gray-700);
  --v-multi-select-height: auto;
  --v-multi-select-min-height: var(--v-input-height);
  --v-multi-select-placeholder-color: var(--v-input-placeholder-color);
  --v-multi-select-border-radius: var(--v-input-border-radius);
  --v-multi-select-padding-x: var(--v-input-padding-x);
  --v-multi-select-padding-y: var(--size-spacing-2);
  --v-multi-select-font-size: var(--v-input-font-size);

  /* label */
  --v-multi-select-label-font-size: var(--v-input-label-font-size);
  --v-multi-select-label-font-weight: var(--v-input-label-font-weight);
  --v-multi-select-label-display: var(--v-input-label-display);
  --v-multi-select-label-margin-bottom: var(--v-input-label-margin-bottom);
  --v-multi-select-label-color: var(--v-input-label-color);

  /* item */
  --v-multi-select-item-font-size: var(--size-font-sm);
  --v-multi-select-item-font-weight: var(--font-weight-regular);
  --v-multi-select-item-bg-color: var(--color-white);
  --v-multi-select-item-text-color: var(--color-gray-800);
  --v-multi-select-item-padding-x: var(--size-spacing-3);
  --v-multi-select-item-padding-y: var(--size-spacing-2);
  --v-multi-select-item-hover-bg-color: var(--color-gray-100);
  --v-multi-select-item-hover-text-color: var(--color-gray-700);

  /* error */
  --v-multi-select-error-border-color: var(--color-error-500);

  /* icon */
  --v-multi-select-icon-color: var(--color-gray-500);
  --v-multi-select-icon-size: var(--size-spacing-5);
  --v-multi-select-check-icon-color: var(--color-primary-700);

  /* dropdown */
  --v-multi-select-dropdown-bg-color: var(--color-white);
  --v-multi-select-dropdown-border-radius: var(--border-radius-lg);

  // hint
  --v-multi-select-hint-font-size: var(--v-input-hint-font-size, 14px);
  --v-multi-select-hint-color: var(--color-gray-500);
  --v-multi-select-hint-margin-top: var(--size-spacing-1);
}
:root {
  --v-multi-select-border-color: var(--v-input-border-color);
  --v-multi-select-border-radius: var(--v-input-border-radius);
  --v-multi-select-bg-color: var(--v-input-bg-color);
  --v-multi-select-text-color: var(--color-gray-700);
  --v-multi-select-height: auto;
  --v-multi-select-min-height: var(--v-input-height);
  --v-multi-select-placeholder-color: var(--v-input-placeholder-color);
  --v-multi-select-border-radius: var(--v-input-border-radius);
  --v-multi-select-padding-x: var(--v-input-padding-x);
  --v-multi-select-padding-y: var(--size-spacing-2);
  --v-multi-select-font-size: var(--v-input-font-size);

  /* label */
  --v-multi-select-label-font-size: var(--v-input-label-font-size);
  --v-multi-select-label-font-weight: var(--v-input-label-font-weight);
  --v-multi-select-label-display: var(--v-input-label-display);
  --v-multi-select-label-margin-bottom: var(--v-input-label-margin-bottom);
  --v-multi-select-label-color: var(--v-input-label-color);

  /* item */
  --v-multi-select-item-font-size: var(--size-font-sm);
  --v-multi-select-item-font-weight: var(--font-weight-regular);
  --v-multi-select-item-bg-color: var(--color-white);
  --v-multi-select-item-text-color: var(--color-gray-800);
  --v-multi-select-item-padding-x: var(--size-spacing-3);
  --v-multi-select-item-padding-y: var(--size-spacing-2);
  --v-multi-select-item-hover-bg-color: var(--color-gray-100);
  --v-multi-select-item-hover-text-color: var(--color-gray-700);

  /* error */
  --v-multi-select-error-border-color: var(--color-error-500);

  /* icon */
  --v-multi-select-icon-color: var(--color-gray-500);
  --v-multi-select-icon-size: var(--size-spacing-5);
  --v-multi-select-check-icon-color: var(--color-primary-700);

  /* dropdown */
  --v-multi-select-dropdown-bg-color: var(--color-white);
  --v-multi-select-dropdown-border-radius: var(--border-radius-lg);

  // hint
  --v-multi-select-hint-font-size: var(--v-input-hint-font-size, 14px);
  --v-multi-select-hint-color: var(--color-gray-500);
  --v-multi-select-hint-margin-top: var(--size-spacing-1);
}

Standalone Installation

You can also install the Multi Select component individually via @morpheme/multi-select package:

bash
npm i @morpheme/multi-select
npm i @morpheme/multi-select

Then, use it in your component:

vue
<script setup lang="ts">
import {ref} from 'vue';
import VMultiSelect from '@morpheme/multi-select';

const items = ref([
  {
    text: 'Item 1',
    value: 1,
  },
  {
    text: 'Item 2',
    value: 2,
  },
  {
    text: 'Item 2',
    value: 2,
  },
]);

const selected = ref();
</script>

<template>
  <VMultiSelect v-model="selected" :items="items" />
</template>
<script setup lang="ts">
import {ref} from 'vue';
import VMultiSelect from '@morpheme/multi-select';

const items = ref([
  {
    text: 'Item 1',
    value: 1,
  },
  {
    text: 'Item 2',
    value: 2,
  },
  {
    text: 'Item 2',
    value: 2,
  },
]);

const selected = ref();
</script>

<template>
  <VMultiSelect v-model="selected" :items="items" />
</template>

Storybook

View Storybook documentation here.