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
Name | Type | Default |
---|---|---|
items | Array as PropType<VMultiSelectItem[]> | [] |
itemText | string | 'text' |
itemValue | string | value |
searchBy | string | '' |
placeholder | string | 'Search...' |
name | string | '' |
error | boolean | false |
errorMessages | Array | '[]' |
clearable | boolean | 'false' |
disabled | boolean | 'false' |
readonly | boolean | 'false' |
maxBadge | number | 0 |
delay | number | '500' |
id | string | '' |
inputProps | Object as PropType<Record<string, any>> | '{}' |
selectAll | boolean | false |
loading | boolean | false |
wrapperClass | string | '' |
inputClass | string | '' |
badgeColor | string | 'primary' |
badgeClass | string | '' |
badgeProps | object | {} |
dropdownClass | string | '' |
itemClass | string | '' |
checkWrapperClass | string | '' |
checkIconClass | string | '' |
noDataClass | string | '' |
loadingClass | string | '' |
label | string | '' |
labelClass | string | 'mb-2 block' |
rules | string | '' |
errorClass | string | 'text-error-600 mt-1 text-sm' |
transition | string | 'fade' |
hint | String | '' |
hideError | Boolean | false |
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.
<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.
<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>
search
This event is emitted when the user performs a search in the VMultiSelect
component. It is emitted with the search query string.
<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.
<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
Prop | Value | Description |
---|---|---|
index | number | Index of the current selection |
item | any | Current selected item at given index |
value | string | Label of selected item. |
onRemove | function | Callback 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
Prop | Value | Description |
---|---|---|
length | number | Number 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
Prop | Value | Description |
---|---|---|
iSelected | boolean | A flag to indicate if all options is currently selected |
onClick | function | Callback 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
Prop | Value | Description |
---|---|---|
index | number | Index of the current selection |
item | any | Current selected item at given index |
value | string | Label of selected item. |
iSelected | boolean | A flag to indicate if it is currently selected |
CSS Variables
: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:
npm i @morpheme/multi-select
npm i @morpheme/multi-select
Then, use it in your component:
<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.