Vue 3 compatible multiselect component with advanced selection, search, tagging, and grouping capabilities
npx @tessl/cli install tessl/npm-vue-multiselect@3.3.0Vue Multiselect is a comprehensive Vue 3 compatible multiselect component library that provides advanced selection capabilities for web applications. It offers multiple selection modes including single select, multiple select, tagging, and dropdown functionality with built-in search and filtering capabilities.
npm install vue-multiselectimport VueMultiselect from 'vue-multiselect'Named imports:
import { Multiselect, multiselectMixin, pointerMixin } from 'vue-multiselect'<template>
<div>
<VueMultiselect
v-model="selected"
:options="options"
placeholder="Select option"
label="name"
track-by="id">
</VueMultiselect>
</div>
</template>
<script>
import VueMultiselect from 'vue-multiselect'
export default {
components: { VueMultiselect },
data() {
return {
selected: null,
options: [
{ id: 1, name: 'Option 1' },
{ id: 2, name: 'Option 2' },
{ id: 3, name: 'Option 3' }
]
}
}
}
</script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>Vue Multiselect is built around several key components:
Multiselect Vue component providing the complete UI and functionalitymultiselectMixin and pointerMixin for reusabilityVue Multiselect uses a modular mixin architecture to separate concerns:
multiselectMixin - Core functionality including:
pointerMixin - Navigation and highlighting including:
// Import mixins for custom components
import { multiselectMixin, pointerMixin } from 'vue-multiselect';
// Use in custom Vue component
export default {
mixins: [multiselectMixin, pointerMixin],
// Your custom implementation
}Core single and multiple selection functionality with v-model support. Handles objects, arrays, strings, and numbers as option values.
// Component props for basic selection
interface BasicSelectionProps {
modelValue?: any | any[];
options: any[];
multiple?: boolean;
trackBy?: string;
label?: string;
placeholder?: string;
disabled?: boolean;
}Built-in search functionality with configurable filtering, custom search functions, and async option loading support.
// Component props for search and filtering
interface SearchFilteringProps {
searchable?: boolean;
internalSearch?: boolean;
clearOnSelect?: boolean;
preserveSearch?: boolean;
customLabel?: (option: any, label: string) => string;
filteringSortFunc?: (a: any, b: any) => number;
}Advanced tagging functionality allowing users to create new options dynamically through text input.
// Component props for tagging
interface TaggingProps {
taggable?: boolean;
tagPlaceholder?: string;
tagPosition?: 'top' | 'bottom';
}
// Component events for tagging
interface TaggingEvents {
'@tag': (searchQuery: string, id: string | number) => void;
}Support for hierarchical option structures with group selection capabilities and custom group rendering.
// Component props for grouped options
interface GroupedOptionsProps {
groupValues?: string;
groupLabel?: string;
groupSelect?: boolean;
}Extensive configuration options for behavior control, limits, keyboard handling, and UI customization.
// Component props for advanced configuration
interface AdvancedConfigProps {
max?: number | boolean;
limit?: number;
limitText?: (count: number) => string;
closeOnSelect?: boolean;
clearOnSelect?: boolean;
hideSelected?: boolean;
allowEmpty?: boolean;
resetAfter?: boolean;
loading?: boolean;
}Comprehensive slot system enabling complete customization of all UI elements including options, tags, labels, and controls.
// Component slots for custom rendering
interface CustomRenderingSlots {
caret: { toggle: () => void };
clear: { search: string };
selection: { search: string; remove: (option: any) => void; values: any[]; isOpen: boolean };
tag: { option: any; search: string; remove: (option: any) => void };
option: { option: any; search: string; index: number };
singleLabel: { option: any };
noResult: { search: string };
noOptions: {};
}All component events for handling user interactions and state changes.
// Component events
interface MultiselectEvents {
/** Fired when dropdown opens */
'@open': (id: string | number | null) => void;
/** Fired when dropdown closes */
'@close': (value: any, id: string | number | null) => void;
/** Fired when option is selected */
'@select': (option: any, id: string | number | null) => void;
/** Fired when option is removed */
'@remove': (option: any, id: string | number | null) => void;
/** Fired when value changes (v-model) */
'@update:modelValue': (newValue: any) => void;
/** Fired when search input changes */
'@search-change': (searchValue: string) => void;
/** Fired when new tag is created */
'@tag': (tagLabel: string, id: string | number | null) => void;
}Public methods that can be called via template refs.
// Component methods accessible via template refs
interface MultiselectMethods {
/** Opens the multiselect dropdown */
activate(): void;
/** Closes the multiselect dropdown */
deactivate(): void;
/** Toggles the dropdown open/closed state */
toggle(): void;
/** Add/remove given option from selected options */
select(option: any, key?: string): void;
/** Remove given option from selected options */
removeElement(option: any, shouldClose?: boolean): void;
/** Remove the last selected element */
removeLastElement(): void;
/** Updates the search value */
updateSearch(query: string): void;
/** Check if given element is selected */
isSelected(option: any): boolean;
/** Get display label for option */
getOptionLabel(option: any): string;
}Complete slot system for custom UI rendering.
// Component slots for custom rendering
interface MultiselectSlots {
/** Override entire selection display */
selection: { search: string; remove: (option: any) => void; values: any[]; isOpen: boolean };
/** Override individual tag display */
tag: { option: any; search: string; remove: (option: any) => void };
/** Override single selection label */
singleLabel: { option: any };
/** Override placeholder content */
placeholder: {};
/** Override limit text when selections exceed limit */
limit: {};
/** Override individual option display */
option: { option: any; search: string; index: number };
/** Content before options list */
beforeList: {};
/** Content after options list */
afterList: {};
/** Message when search returns no results */
noResult: { search: string };
/** Message when no options available */
noOptions: {};
/** Message when max selections reached */
maxElements: {};
/** Override dropdown arrow/caret */
caret: { toggle: () => void };
/** Override clear button */
clear: { search: string };
/** Override loading spinner */
loading: {};
}// Complete component props interface
interface MultiselectProps {
// Core selection props
modelValue?: any | any[];
options: any[];
multiple?: boolean;
trackBy?: string;
label?: string;
placeholder?: string;
disabled?: boolean;
allowEmpty?: boolean;
// Search and filtering props
searchable?: boolean;
internalSearch?: boolean;
clearOnSelect?: boolean;
preserveSearch?: boolean;
customLabel?: (option: any, label: string) => string;
filteringSortFunc?: (a: any, b: any) => number;
// Tagging props
taggable?: boolean;
tagPlaceholder?: string;
tagPosition?: 'top' | 'bottom';
// Grouped options props
groupValues?: string;
groupLabel?: string;
groupSelect?: boolean;
// Advanced configuration props
max?: number | boolean;
limit?: number;
limitText?: (count: number) => string;
closeOnSelect?: boolean;
hideSelected?: boolean;
resetAfter?: boolean;
loading?: boolean;
optionsLimit?: number;
blockKeys?: string[];
preselectFirst?: boolean;
preventAutofocus?: boolean;
// Component-specific props
name?: string;
selectLabel?: string;
selectGroupLabel?: string;
selectedLabel?: string;
deselectLabel?: string;
deselectGroupLabel?: string;
showLabels?: boolean;
maxHeight?: number;
spellcheck?: boolean;
openDirection?: string;
showNoOptions?: boolean;
showNoResults?: boolean;
tabindex?: number;
required?: boolean;
// Pointer/navigation props
showPointer?: boolean;
optionHeight?: number;
// Additional utility props
id?: string | number | null;
}
// Mixin interfaces
interface MultiselectMixinProps {
internalSearch?: boolean;
options: any[];
multiple?: boolean;
trackBy?: string;
label?: string;
searchable?: boolean;
clearOnSelect?: boolean;
hideSelected?: boolean;
placeholder?: string;
allowEmpty?: boolean;
resetAfter?: boolean;
closeOnSelect?: boolean;
customLabel?: (option: any, label: string) => string;
taggable?: boolean;
tagPlaceholder?: string;
tagPosition?: string;
max?: number | boolean;
id?: string | number | null;
optionsLimit?: number;
groupValues?: string;
groupLabel?: string;
groupSelect?: boolean;
blockKeys?: string[];
preserveSearch?: boolean;
preselectFirst?: boolean;
preventAutofocus?: boolean;
filteringSortFunc?: (a: any, b: any) => number;
}
interface PointerMixinProps {
showPointer?: boolean;
optionHeight?: number;
}
// Component definition with Vue 3 Composition API
interface MultiselectComponent extends DefineComponent<
MultiselectProps,
{},
{},
{},
MultiselectMethods
> {}
// Main exports
export const Multiselect: MultiselectComponent;
export const multiselectMixin: DefineComponent<MultiselectMixinProps>;
export const pointerMixin: DefineComponent<PointerMixinProps>;
export default Multiselect;