vue-multiselect
Probably the most complete selecting solution for Vue.js, without jQuery.
Features & characteristics:
- NO dependencies
- Single select
- Multiple select
- Tagging
- Dropdowns
- Filtering
- Search with suggestions
- Logic split into mixins
- Basic component and support for custom components
- Vuex support
- Async options support
- > 95% test coverage
- Fully configurable (see props list below)
Demo & docs
http://monterail.github.io/vue-multiselect/
Install & basic usage
npm install vue-multiselect
<template>
<div>
<multiselect :selected.sync="selected" :options="options"></multiselect>
</div>
</template>
It is very important not to mix .sync
with :on-change
prop. You have to either choose two-way binding or one way binding with :on-change
callback as a way to update the :selected
value
import Multiselect from 'vue-multiselect'
export default {
components: { Multiselect },
data () {
return {
selected: null,
options: ['list', 'of', 'options']
}
}
}
You can now author custom components based on vue-multiselect mixins.
import { multiselectMixin, pointerMixin } from 'vue-multiselect'
export default {
mixins: [multiselectMixin, pointerMixin],
data () {
return {
selected: null,
options: ['list', 'of', 'options']
}
}
}
Roadmap:
- 1.0 Release – Event based, deprecate two-way binding, make it easy to migrate to Vue 2.0
- Examples of custom components / templates ready to use in project
- Better documentation
Examples
in jade-lang/pug-lang
Single select / dropdown
multiselect(
:options="source",
:selected.sync="value",
:multiple="false",
:searchable="false",
placeholder="Select one",
label="name",
:close-on-select="false",
:allow-empty="false",
key="name"
)
Single select with search
multiselect(
:options="source",
:selected.sync="value",
:multiple="false",
:searchable="true",
placeholder="Select one",
label="name",
:close-on-select="true",
:clear-on-select="false"
key="name"
)
Multiple select with search
multiselect(
:options="source",
:selected.sync="multiValue",
:multiple="true",
:searchable="true",
placeholder="Pick some",
label="name",
:close-on-select="true"
key="name"
)
Tagging
with :on-tag
and :on-change
callback functions
multiselect(
:options="taggingOptions",
:selected="taggingSelected",
:multiple="multiple",
:searchable="searchable",
:on-tag="addTag",
:on-change="updateSelectedTagging",
:taggable="true",
tag-placeholder="Add this as new tag"
placeholder="Type to search or add tag"
label="name"
key="code"
)
addTag (newTag) {
const tag = {
name: newTag,
code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.taggingOptions.push(tag)
this.taggingSelected.push(tag)
},
Vuex supporting example
with :on-change
callback function
multiselect(
:options="source",
:selected="value",
:multiple="false",
:searchable="false",
placeholder="Select one",
:on-change="onChangeAction"
)
methods: {
onChangeAction (newValue) {
dispatch('SET_SELECT_VALUE', newValue)
}
}
Asynchronous dropdown
multiselect(
:options="countries",
:selected.sync="selectedCountries",
:multiple="multiple",
:searchable="searchable",
placeholder="Type to search",
:on-search-change="asyncFind",
label="name"
key="code"
)
span(slot="noResult").
Oops! No elements found. Consider changing the search query.
methods: {
asyncFind (query) {
this.countries = findService(query)
}
}
Props config
props: {
options: {
type: Array,
required: true
},
multiple: {
type: Boolean,
default: false
},
selected: {
required: true
},
key: {
type: String,
default: false
},
label: {
type: String,
default: false
},
searchable: {
type: Boolean,
default: true
},
clearOnSelect: {
type: Boolean,
default: true
},
hideSelected: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: 'Select option'
},
maxHeight: {
type: Number,
default: 300
},
allowEmpty: {
type: Boolean,
default: true
},
onChange: {
type: Function,
default: false
},
onSearchChange: {
type: Function,
default: false
},
touched: {
type: Boolean,
default: false
},
resetAfter: {
type: Boolean,
default: false
},
closeOnSelect: {
type: Boolean,
default: true
},
customLabel: {
type: Function,
default: false
},
taggable: {
type: Boolean,
default: false
},
onTag: {
type: Function,
default: function (tag) {
this.options.push(tag)
this.value.push(tag)
}
},
tagPlaceholder: {
type: String,
default: 'Press enter to create a tag'
},
max: {
type: Number,
default: false
}
}
props: {
showPointer: {
type: Boolean,
default: true
}
}
props: {
selectLabel: {
type: String,
default: 'Press enter to select'
},
selectedLabel: {
type: String,
default: 'Selected'
},
deselectLabel: {
type: String,
default: 'Press enter to remove'
},
showLabels: {
type: Boolean,
default: true
},
limit: {
type: Number,
default: 99999
},
limitText: {
type: Function,
default: count => `and ${count} more`
}
}
Contributing
npm run dev
npm run bundle
npm run docs
npm run test
npm run unit-watch
For detailed explanation on how things work, checkout the guide and docs for vue-loader.