- @vueform/slider - Vue 3 slider component with multihandles, tooltips merging and formatting.
- @vueform/toggle - Vue 3 toggle component with labels, custom slots and styling options.
- Vue 2 & 3 support
- No dependencies
- Lightweight (<6 kB gzipped)
- 100% coverage
- TypeScript support
- ESM support
- Single select options
- Multiple select options
- Tags
- Async options
- Search & filtering
- Custom slots
- Events
- Fully configurable
Check out our demo.
npm install @vueform/multiselect
<template>
<div>
<Multiselect
v-model="value"
:options="options"
/>
</div>
</template>
<script>
import Multiselect from '@vueform/multiselect'
export default {
components: {
Multiselect,
},
data() {
return {
value: null,
options: [
'Batman',
'Robin',
'Joker',
]
}
}
}
</script>
<style src="@vueform/multiselect/themes/default.css"></style>
When using with Vue 2 make sure to install @vue/composition-api first and change the imported module to:
import Multiselect from '@vueform/multiselect/dist/multiselect.vue2.js'
Join our Discord channel or open an issue.
Name | Type | Default | Description |
---|---|---|---|
mode | string |
single |
Possible values: single|multiple|tags . |
options | array|object|function |
[] |
List of options. Can be: - an array (eg. [1,2,3] )- an object (eg. {a:1,b:2,c:3} )- an array of objects [{value:1,label:'v1'},{value:2,label:'v2'},{value:3,label:'v3',disabled:true}] - a function returning a Promise (async function) with query input param. The promise should return options as an object or as an array of objects.When an array of objects is provided it must have properties that equal to :valueProp 's, :trackBy 's and :label 's value. |
searchable | boolean |
false |
Whether the options should be searchable. |
valueProp | string |
'value' |
If you provide an array of objects as options this property should be used as the value of the option. |
trackBy | string |
'label' |
The name of the property that should be searched when searchable is true and an array of objects are provided as :options . |
label | string |
'label' |
If you provide an array of objects as options the value this property will be displayed as selected option. |
placeholder | string |
null |
The text that should be displayed before any option is selected. |
multipleLabel | function |
A function that returns the label to be displayed for selected options when using multiple mode. It receives value as an argument. By default it renders 1 option selected and [n] options selected based on value length. |
|
disabled | boolean |
false |
Whether the input should be disabled for the user (API can still be used programmatically). |
max | number |
-1 |
The maximum number of options that can be selected when using multiple or tags mode. If -1 the number of options won't be limited. |
limit | number |
-1 |
The maximum number of options that should be displayed. If -1 the number of options won't be limited. |
loading | boolean |
false |
Whether a loading spinner should be shown. |
id | string |
'multiselect' |
The id of the multiselect container DOM. |
caret | boolean |
true |
Whether should display the caret symbol on the right. |
maxHeight | number |
160 |
The maximum height of options list (px). |
noOptionsText | string |
'The list is empty' |
The text that should be displayed when options list is empty. |
noResultsText | string |
'No results found' |
The text that should be displayed when there are no search results. |
Name | Type | Default | Description |
---|---|---|---|
canDeselect | boolean |
true |
Whether a selected option can be deselected when using single mode. |
clearOnSearch | boolean |
false |
Whether the option list should be cleared when a new character is typed before loading new options list, when using async options. |
clearOnSelect | boolean |
true |
Whether the option list should be cleared upon selecting an option when using async options. |
delay | number |
-1 |
The delay in milliseconds that should occur between the last typed character and refreshing an async option list. If -1 the option list will not refresh when the search query changes. If 0 it will refresh without delay. |
filterResults | boolean |
true |
Whether option list should be filtered by search query. This may be set to false if you are handling filtering manually when returning async options. |
minChars | number |
0 |
The minimum number of characters that should be typed to refresh async option list. If 0 it will refresh even when the search field becomes empty. |
resolveOnLoad | boolean |
true |
Whether async options should be loaded initially (with an empty query). This should be true if you are planning to load non-object value(s) initially while using async options (to fetch matching objects for values). |
appendNewTag | boolean |
true |
Whether it should append new tag automatically to option list when using tags mode with createTag . If set to false you need to take care of appending a new tag to the provided :options list upon @tag event. |
createTag | boolean |
false |
Whether it should allow creating new tag based on search query when using tags mode. |
hideSelected | boolean |
true |
Whether selected options should be excluded from the option list when using multiple or tags mode. |
object | boolean |
false |
Whether the value should be stored as an object. If false: value: ['js','jsx','ts'] If true: value: [ {value:'js',label:'Javascript'}, {value:'jsx',label:'JSX'}, {value:'ts',label:'Typescript'} ] |
Name | Params | Description |
---|---|---|
open | Opens the options list and focuses the multiselect. | |
close | Closes the options list and blurs the multiselect. | |
select | value |
Selects an option based on its value. |
deselect | value |
Deselects an option based on its value. |
remove | value |
Alias for deselect . |
clear | Deselects all selected options. | |
refreshOptions | callback |
Refreshes async options list. |
To access API use ref
on Multiselect
component:
<Multiselect
v-model="value"
:options="options"
ref="multiselect"
/>
// eg:
mounted() {
this.$refs.multiselect.open()
}
Event | Attributes | Description |
---|---|---|
@change | value |
Emitted after the value is changed. |
@close | Emitted after closing the option list. | |
@deselect | option |
Emitted after an option is deselected or a tag is removed. |
@open | Emitted after opening the option list. | |
@search-change | query |
Emitted after a character is typed. |
@select | option |
Emitted after an option or tag is selected. |
@tag | query |
Emitted after enter is hit when a new tag is being created. |
Slot | Attributes | Description |
---|---|---|
placeholder | Rendered as placeholder when the multiselect does not have value and placeholder prop is defined. |
|
afterlist | Rendered after the options list. | |
beforelist | Rendered before the options list. | |
multiplelabel | values |
Rendered when using multiple mode and options are selected. By default it renders the return value of multipleLabel function. |
nooptions | Rendered when the options list is empty. By default renders noOptionsText . |
|
noresults | Rendered when there are no search results. By default renders noResultsText . |
|
option | option, search |
Renders an option in options list. |
singlelabel | value |
Rendered when using single mode and an option is selected. By default it renders the :label if the selected option. |
tag | option, remove, disabled |
Renders a tag when using tags mode. When disabled the remove icon should not be displayed. The remove prop should be used to trigger the removal of the tag. |
Note: we don't use camelCase because they are normalized back to lowercase when written in DOM.
- Single select
- Multiselect with object options
- Multiselect with disabled options
- Tags with search, create and array of objects options
- Autocomplete with async options
- Tags with async options
- Select with custom options slot
- Multiselect with custom label slot
- Tags with custom tags slot
<Multiselect
v-model="value"
:options="['Batman', 'Robin', 'Joker']"
/>
<Multiselect
v-model="value"
mode="multiple"
:options="{
batman: 'Batman',
robin: 'Robin',
joker: 'Joker'
}"
/>
<Multiselect
v-model="value"
mode="multiple"
:options="[
{ value: 'batman', label: 'Batman' },
{ value: 'robin', label: 'Robin', disabled: true },
{ value: 'joker', label: 'Joker' },
]"
/>
<Multiselect
v-model="value"
mode="tags"
:searchable="true"
:createTag="true"
:options="[
{ value: 'batman', label: 'Batman' },
{ value: 'robin', label: 'Robin' },
{ value: 'joker', label: 'Joker' },
]"
/>
<Multiselect
v-model="value"
placeholder="Choose a programming language"
:filterResults="false"
:minChars="1"
:resolveOnLoad="false"
:delay="0"
:searchable="true"
:options="async function(query) {
return await fetchLanguages(query) // check JS block in JSFiddle for implementation
}"
/>
<Multiselect
v-model="value"
mode="tags"
placeholder="Choose your stack"
:filterResults="false"
:minChars="1"
:resolveOnLoad="false"
:delay="0"
:searchable="true"
:options="async function(query) {
return await fetchLanguages(query) // check JS block in JSFiddle for implementation
}"
/>
<Multiselect
v-model="value"
placeholder="Select your character"
label="name"
:options="[
{ value: 'captainamerica', name: 'Captain America', icon: 'https://cdn2.iconfinder.com/data/icons/avengers-filled/48/03_-_Captain_America_-_infinity_war_-_end_game_-_marvel_-_avengers_-_super_hero-512.png' },
{ value: 'spiderman', name: 'Spiderman', icon: 'https://cdn2.iconfinder.com/data/icons/avengers-filled/48/12_-_Spiderman_-_infinity_war_-_end_game_-_marvel_-_avengers_-_super_hero-512.png' },
{ value: 'ironman', name: 'Iron Man', icon: 'https://cdn2.iconfinder.com/data/icons/avengers-filled/48/02_-_IRONMAN_-_infinity_war_-_end_game_-_marvel_-_avengers_-_super_hero-512.png' },
]"
>
<template v-slot:singlelabel="{ value }">
<div class="multiselect-single-label">
<img class="character-label-icon" :src="value.icon"> {{ value.name }}
</div>
</template>
<template v-slot:option="{ option }">
<img class="character-option-icon" :src="option.icon"> {{ option.name }}
</template>
</Multiselect>
<Multiselect
v-model="value"
mode="multiple"
placeholder="Select your characters"
:options="{
batman: 'Batman',
robin: 'Robin',
joker: 'Joker'
}"
>
<template v-slot:multiplelabel="{ values }">
<div class="multiselect-multiple-label">
{{ values.length }} characters selected
</div>
</template>
</Multiselect>
<template>
<Multiselect
v-model="value"
mode="tags"
placeholder="Select employees"
trackBy="name"
label="name"
:search="true"
:options="[
{ value: 'judy', name: 'Judy', image: 'https://randomuser.me/api/portraits/med/women/1.jpg' },
{ value: 'jane', name: 'Jane', image: 'https://randomuser.me/api/portraits/med/women/2.jpg' },
{ value: 'john', name: 'John', image: 'https://randomuser.me/api/portraits/med/men/1.jpg' },
{ value: 'joe', name: 'Joe', image: 'https://randomuser.me/api/portraits/med/men/2.jpg' }
]"
>
<template v-slot:tag="{ option, handleTagRemove, disabled }">
<div class="multiselect-tag is-user">
<img :src="option.image">
{{ option.name }}
<i
v-if="!disabled"
@click.prevent
@mousedown.prevent.stop="handleTagRemove(option, $event)"
/>
</div>
</template>
</Multiselect>
</template>
<style>
.multiselect-tag.is-user {
padding: 5px 8px;
border-radius: 22px;
background: #35495e;
margin: 3px 3px 8px;
}
.multiselect-tag.is-user img {
width: 18px;
border-radius: 50%;
height: 18px;
margin-right: 8px;
border: 2px solid #ffffffbf;
}
.multiselect-tag.is-user i:before {
color: #ffffff;
border-radius: 50%;;
}
.user-image {
margin: 0 6px 0 0;
border-radius: 50%;
height: 22px;
}
</style>
Vueform streamlines the entire form building process in Vue 2 & 3. It comes with 30+ elements, file uploads, element nesting, 50+ validators, conditions, form steps, i18n including reactive configuration, API access, ESM modules and many more. Check out our live demos or see all the features and sign up for beta to get early access.