1. Project Overview & Quickstart (sagalbot/vue-select)
File: README.md
vue-select [](https://coveralls.io/github/sagalbot/vue-select?branch=master)
Everything you wish the HTML
<select>element could do, wrapped up into a lightweight, zero
dependency, extensible Vue component.
Vue Select is a feature rich select/dropdown/typeahead component. It provides a default
template that fits most use cases for a filterable select dropdown. The component is designed to be as
lightweight as possible, while maintaining high standards for accessibility,
developer experience, and customization.
- Tagging
- Filtering / Searching
- Vuex Support
- AJAX Support
- SSR Support
- Accessible
- ~20kb Total / ~5kb CSS / ~15kb JS
- Select Single/Multiple Options
- Customizable with slots and SCSS variables
- Zero dependencies
Documentation
Complete documentation and examples available at https://vue-select.org.
Sponsors :tada:
It takes a lot of effort to maintain this project. If it has saved you development time, please consider sponsoring the project
with GitHub sponsors!
Huge thanks to the sponsors and contributors that make Vue Select possible!
Get started
Vue 3 / Vue Select 4.x-beta
Vue 3 support is on the
betachannel:vue-select@beta, and will become the new default whenv4is released. See #1579 for more details!
Install:
yarn add vue-select@beta
# or use npm
npm install vue-select@betaThen, import and register the component:
# main.ts or main.js
import { createApp } from "vue";
import App from "./App.vue";
import { VueSelect } from "vue-select";
createApp(App)
.component("v-select", VueSelect)
.mount("#app");The component itself does not include any CSS. You'll need to include it separately in your Component.vue:
<style>
@import "vue-select/dist/vue-select.css";
</style>Vue 2 / Vue Select 3.x
Install:
yarn add vue-select
# or use npm
npm install vue-selectThen, import and register the component:
import Vue from "vue";
import vSelect from "vue-select";
Vue.component("v-select", vSelect);The component itself does not include any CSS. You'll need to include it separately:
import "vue-select/dist/vue-select.css";You can also include vue-select directly in the browser. Check out the
documentation for loading from CDN..
License
File: docs/api/events.md
`input`
Triggered when the selected value changes. Used internally for v-model.
/**
* @param {Object|String} val - selected option.
*/
this.$emit("input", val);`open`
Triggered when the dropdown is open.
this.$emit("open");`close`
Triggered when the dropdown is closed.
this.$emit("close");`option:selecting`
Triggered after an option has been selected, before updating internal state.
this.$emit("option:selecting", selectedOption);`option:selected`
Triggered when an option has been selected, after updating internal state.
this.$emit("option:selected", selectedOption);`option:deselecting`
Triggered when an option has been deselected, before updating internal state.
this.$emit("option:deselecting", selectedOption);`option:deselected`
Triggered when an option has been deselected, after updating internal state.
this.$emit("option:deselected", deselectedOption);`option:created`
Triggered when taggable is true and a new option has been created.
/**
* @param {Object} newOption - created option
*/
this.$emit("option:created", newOption);`search`
Anytime the search string changes, emit the
'search' event. The event is passed with two
parameters: the search string, and a function
that accepts a boolean parameter to toggle the
loading state.
See the AJAX Guide
for a complete example.
/**
* @param {String} searchString - the search string
* @param {Function} toggleLoading - function to toggle loading state, accepts true or false boolean
*/
this.$emit('search', this.search, this.toggleLoading);<v-select
@search="(search, loading) => {
loading(true)
fetchOptions(search).then(() => loading(false))
}"
/>`search:blur`
Triggered when the text input loses focus. The dropdown will close immediately before this
event is triggered.
this.$emit("search:blur");`search:focus`
Triggered when the text input gains focus. The dropdown will open immediately before this
event is triggered.
this.$emit("search:focus");File: docs/api/props.md
appendToBody
Append the dropdown element to the end of the body
and size/position it dynamically. Use it if you have
overflow or z-index issues.
See Dropdown Position for more details.
appendToBody: {
type: Boolean,
default: false
},autocomplete
The value provided here will be bound to the autocomplete
HTML attribute
on the search input. Defaults to off.
autocomplete: {
type: String,
default: 'off'
},autoscroll
When true, the dropdown will automatically scroll to ensure
that the option highlighted is fully within the dropdown viewport
when navigating with keyboard arrows.
autoscroll: {
type: Boolean,
default: true
}calculatePosition
When appendToBody is true, this function is responsible for positioning the drop down list.
If a function is returned from calculatePosition, it will be called when the drop down list
is removed from the DOM. This allows for any garbage collection you may need to do.
See Dropdown Position for more details.
calculatePosition: {
type: Function,
/**
* @param dropdownList {HTMLUListElement}
* @param component {Vue} current instance of vue select
* @param width {string} calculated width in pixels of the dropdown menu
* @param top {string} absolute position top value in pixels relative to the document
* @param left {string} absolute position left value in pixels relative to the document
* @return {function|void}
*/
default(dropdownList, component, {width, top, left}) {
dropdownList.style.top = top;
dropdownList.style.left = left;
dropdownList.style.width = width;
}
}clearable
Can the user clear the selected property?
clearable: {
type: Boolean,
default: true
},clearSearchOnBlur
Enables/disables clearing the search text when the search input is blurred.
clearSearchOnBlur: {
type: Function,
default: function ({ clearSearchOnSelect, multiple }) {
return clearSearchOnSelect && !multiple
}
},clearSearchOnSelect
Enables/disables clearing the search text when an option is selected.
clearSearchOnSelect: {
type: Boolean,
default: true
},closeOnSelect
Close a dropdown when an option is chosen. Set to false to keep the dropdown
open (useful when combined with multi-select, for example)
closeOnSelect: {
type: Boolean,
default: true
},components
API to overwrite default vue-select components with your own. This can be used to change the clear button or select chevron with your own markup.
The object provided to the components prop will be merged with Vue Select's default components.
See Components guide for more details.
import Deselect from './Deselect';
import OpenIndicator from './OpenIndicator';
// ...
components: {
type: Object,
default: function () {
Deselect,
OpenIndicator
}
},createOption
User defined function for adding Options
createOption: {
type: Function,
default(newOption) {
if (typeof this.optionList[0] === 'object') {
newOption = {[this.label]: newOption}
}
this.$emit('option:created', newOption)
return newOption
}
},deselectFromDropdown
Determines whether the user can deselect an option by clicking
it from within the dropdown menu.
deselectFromDropdown: {
type: Boolean,
default: false
},dir
Sets RTL support. Accepts ltr, rtl, auto.
dir: {
type: String,
default: "auto"
},disabled
Disable the entire component.
disabled: {
type: Boolean,
default: false
},dropdownShouldOpen
Determines whether the dropdown should open. Used
for overriding the default dropdown behaviour. Receives
the vue-select instance as the single argument to the function.
dropdownShouldOpen: {
type: Function,
default({noDrop, open, mutableLoading}) {
return noDrop ? false : open && !mutableLoading;
}
}filter
Callback to filter results when search text
is provided. Default implementation loops
each option, and returns the result of
this.filterBy.
filter: {
type: Function,
default(options, search) {
return options.filter(option => {
let label = this.getOptionLabel(option);
if (typeof label === "number") {
label = label.toString();
}
return this.filterBy(option, label, search);
});
}
},filterable
When true, existing options will be filtered
by the search text. Should not be used in conjunction
with taggable.
filterable: {
type: Boolean,
default: true
},filterBy
Callback to determine if the provided option should
match the current search text. Used to determine
if the option should be displayed.
filterBy: {
type: Function,
default(option, label, search) {
return (label || '').toLocaleLowerCase().indexOf(search.toLocaleLowerCase()) > -1
}
},getOptionKey
Callback to get an option key. If option
is an object and has an id, returns option.id
by default, otherwise tries to serialize option
to JSON.
The key must be unique for an option.
getOptionKey: {
type: Function,
default(option) {
if (typeof option === 'object' && option.id) {
return option.id
} else {
try {
return JSON.stringify(option)
} catch(e) {
return console.warn(
`[vue-select warn]: Could not stringify option ` +
`to generate unique key. Please provide 'getOptionKey' prop ` +
`to return a unique key for each option.\n` +
'https://vue-select.org/api/props.html#getoptionkey'
)
return null
}
}
}
},getOptionLabel
Callback to generate the label text. If {option}
is an object, returns option[this.label] by default.
Label text is used for filtering comparison and
displaying. If you only need to adjust the
display, you should use the option andselected-option slots.
getOptionLabel: {
type: Function,
default(option) {
if (typeof option === 'object') {
if (!option.hasOwnProperty(this.label)) {
return console.warn(
`[vue-select warn]: Label key "option.${this.label}" does not` +
` exist in options object ${JSON.stringify(option)}.\n` +
'https://vue-select.org/api/props.html#getoptionlabel'
)
}
return option[this.label]
}
return option;
}
},inputId
Sets the id of the input element.
inputId: {
type: String
},label
Tells vue-select what key to use when generating option
labels when each option is an object.
label: {
type: String,
default: "label"
},loading
Show spinner if the component is in a loading state.
loading: {
type: Boolean,
default: false
},maxHeight
::: warning Deprecated in v2.x & Removed in v3.0
This prop was removed in v3.0. You can use the $vs-dropdown-max-height
SCSS variable to adjust this setting in v3.x.
:::
Sets the max-height property on the dropdown list.
maxHeight: {
type: String,
default: "400px"
},multiple
Equivalent to the multiple attribute on a <select> input.
multiple: {
type: Boolean,
default: false
},noDrop
Disable the dropdown entirely.
noDrop: {
type: Boolean,
default: false
},onTab
Select the current value if selectOnTab is enabled.
onTab: {
type: Function,
default: function() {
if (this.selectOnTab) {
this.typeAheadSelect();
}
}
},options
An array of strings or objects to be used as dropdown choices.
If you are using an array of objects, vue-select will look for
a label key (ex. [{label: 'Canada', value: 'CA'}]). A
custom label key can be set with the label prop.
options: {
type: Array,
default() {
return [];
}
},placeholder
Equivalent to the placeholder attribute on an ``.
placeholder: {
type: String,
default: ""
},pushTags
When true, newly created tags will be added to
the options list.
pushTags: {
type: Boolean,
default: false
},reduce
When working with objects, the reduce
prop allows you to transform a given
object to only the information you
want passed to a v-model binding
or @input event.
reduce: {
type: Function,
default: option => option,
},resetOnOptionsChange
When false, updating the options will not reset the selected value.
Since v3.4+ the prop accepts either a boolean or function that returns a boolean.
If defined as a function, it will receive the params listed below.
/**
* @type {Boolean|Function}
* @param {Array} newOptions
* @param {Array} oldOptions
* @param {Array} selectedValue
*/
resetOnOptionsChange: {
default: false,
validator: (value) => ['function', 'boolean'].includes(typeof value)
},searchable
Enable/disable filtering the options.
searchable: {
type: Boolean,
default: true
},selectable
The selectable prop determines if an option is selectable or not. If selectable returns false
for a given option, it will be displayed with a vs__dropdown-option--disabled class. The option
will be disabled and unable to be selected.
selectable: {
type: Function,
/**
* @param {Object|String} option
* @return {boolean}
*/
default: option => true,
},selectOnTab
When true, hitting the 'tab' key will select the current select value
selectOnTab: {
type: Boolean,
default: false
}tabindex
Set the tabindex for the input field.
tabindex: {
type: Number,
default: null
},taggable
Enable/disable creating options from searchInput.
taggable: {
type: Boolean,
default: false
},transition
Sets a Vue transition property on the .dropdown-menu. vue-select
does not include CSS for transitions, you'll need to add them yourself.
transition: {
type: String,
default: "fade"
},uid
A unique identifier used to generate IDs and DOM attributes.
Must be unique for every instance of the component.
uid: {
type: [String, Number],
default: () => uniqueId(),
},value
Contains the currently selected value. Very similar to avalue attribute on an ``. You can listen for changes
using the 'input' event.
value: {
default: null
},File: docs/api/slots.md
::: tip
Vue Select leverages scoped slots to allow for total customization of the presentation layer.
Slots can be used to change the look and feel of the UI, or to simply swap out text.
:::
`footer`
Displayed at the bottom of the component, below .vs__dropdown-toggle.
When implementing this slot, you'll likely need to use appendToBody to position the dropdown.
Otherwise content in this slot will affect it's positioning.
search {string}- the current search queryloading {boolean}- is the component loadingsearching {boolean}- is the component searchingfilteredOptions {array}- options filtered by the search textdeselect {function}- function to deselect an option
`header`
Displayed at the top of the component, above .vs__dropdown-toggle.
search {string}- the current search queryloading {boolean}- is the component loadingsearching {boolean}- is the component searchingfilteredOptions {array}- options filtered by the search textdeselect {function}- function to deselect an option
`list-footer`
Displayed as the last item in the dropdown. No content by default. Parent element is the ``,
so this slot should contain a root <li>.
search {string}- the current search queryloading {boolean}- is the component loadingsearching {boolean}- is the component searchingfilteredOptions {array}- options filtered by the search text
`list-header`
Displayed as the first item in the dropdown. No content by default. Parent element is the ``,
so this slot should contain a root <li>.
search {string}- the current search queryloading {boolean}- is the component loadingsearching {boolean}- is the component searchingfilteredOptions {array}- options filtered by the search text
`no-options`
The no options slot is displayed above list-footer in the dropdown whenfilteredOptions.length === 0.
search {string}- the current search queryloading {boolean}- is the component loadingsearching {boolean}- is the component searching
`open-indicator`
The open indicator is the caret icon on the component used to indicate dropdown status.
attributes: {
'ref': 'openIndicator',
'role': 'presentation',
'class': 'vs__open-indicator',
}`option`
The current option within the dropdown, contained within <li>.
option {Object}- The currently iterated option fromfilteredOptions
`search`
The search input has a lot of bindings, but they're grouped into attributes and events. Most
of the time, you will just be binding those two with v-on="events" and v-bind="attributes".
If you want the default styling, you'll need to add .vs__search to the input you provide.
/**
* Attributes to be bound to a search input.
*/
attributes: {
'disabled': this.disabled,
'placeholder': this.searchPlaceholder,
'tabindex': this.tabindex,
'readonly': !this.searchable,
'id': this.inputId,
'aria-autocomplete': 'list',
'aria-labelledby': `vs${this.uid}__combobox`,
'aria-controls': `vs${this.uid}__listbox`,
'aria-activedescendant': this.typeAheadPointer > -1
? `vs${this.uid}__option-${this.typeAheadPointer}`
: '',
'ref': 'search',
'type': 'search',
'autocomplete': this.autocomplete,
'value': this.search,
},
/**
* Events that this element should handle.
*/
events: {
'compositionstart': () => this.isComposing = true,
'compositionend': () => this.isComposing = false,
'keydown': this.onSearchKeyDown,
'blur': this.onSearchBlur,
'focus': this.onSearchFocus,
'input': (e) => this.search = e.target.value,
}`selected-option`
The text displayed within selected-option-container.
This slot doesn't exist if selected-option-container is implemented.
option {Object}- A selected option
`selected-option-container`
This is the root element where v-for="option in selectedValue". Most of the time you'll want to
use selected-option, but this container is useful if you want to disable the deselect button,
or have fine grain control over the markup.
option {Object}- Currently iterated selected optiondeselect {Function}- Method used to deselect a given option whenmultipleis truedisabled {Boolean}- Determine if the component is disabledmultiple {Boolean}- If the component supports the selection of multiple values
`spinner`
loading {Boolean}- if the component is in a loading state
File: docs/guide/accessibility.md
Vue Select aims to follow the WAI-ARIA best practices for the
combobox and
listbox widgets.
The UX of the component is designed around the HTML <select> element, while following the WAI-ARIA
specifications and best practices for creating accessible components.
Combobox
Listbox
Autocomplete
WAI-ARIA suggests four forms of autocomplete for Comboboxes. Vue Select can be configured to provide
these use cases.
No autocomplete
When the popup is triggered, the suggested values it contains are the same regardless of the
characters typed in the textbox.html<v-select :filterable="false" :options="['No Autocomplete', 'List Autocomplete']" />List autocomplete with manual selection
When the popup is triggered, it presents suggested values that complete or logically
correspond to the characters typed in the textbox. The character string the user has
typed will become the value of the textbox unless the user selects a value in the popup.html<v-select taggable :options="['No Autocomplete', 'List Autocomplete']" />List autocomplete with automatic selection
When the popup is triggered, it presents suggested values that complete or logically
correspond to the characters typed in the textbox, and the first suggestion is automatically
highlighted as selected. The automatically selected suggestion becomes the value of the textbox
when the combobox loses focus unless the user chooses a different suggestion or changes the
character string in the textbox.html<v-select :options="['No Autocomplete', 'List Autocomplete']" />List with inline autocomplete
This is the same as list with automatic selection with one additional feature. The portion of
the selected suggestion that has not been typed by the user, a completion string, appears inline
after the input cursor in the textbox. The inline completion string is visually highlighted and
has a selected state.๐ง Vue Select does not yet support this configuration, but it is on the roadmap
#865. ๐ง
File: docs/guide/ajax.md
Loading Options with AJAX
The search event provides a hook to load options from a parent component
when the search text is updated. It is emitted with two parameters:
Search Event Parameters
search {String}The current search stringloading {Function}Accepts a boolean parameter to toggle the loading state
<v-select @search="fetchOptions" />/**
* Triggered when the search text changes.
*
* @param search {String} Current search text
* @param loading {Function} Toggle loading class
*/
fetchOptions (search, loading) {
// ... do some asynchronous stuff!
},The loading function accepts a boolean parameter that will be assigned
to the vue-select internal loading property. Call loading(true) to set theloading property to true - toggling the loading spinner. After your
asynchronous operation completes, call loading(false) to toggle it off.
Disabling Filtering
When loading server side options, it can be useful to disable the
client side filtering. Use the filterable prop to disable filtering.
/**
* When true, existing options will be filtered
* by the search text. Should not be used in
* conjunction with taggable.
*
* @type {Boolean}
*/
filterable: {
type: Boolean,
default: true
},Loading Spinner
Vue Select includes a default loading spinner that appears when the loading class is present. Thespinner slot allows you to implement your own spinner.
Loading...Library Agnostic
Since Vue.js does not ship with ajax functionality as part of the core library, it's up to you to
process the ajax requests in your parent component.
I recommend using axios for creating your applications HTTP layer,
or fetch() for simple requests.
Example
The codepen example wraps up all the above concepts and
searches GitHub repositories. It also uses scoped slots to add some custom templating.
File: docs/guide/components.md
Prop: `components` `{Object}`
Vue Select utilizes child components throughout, and exposes an API to overwrite these components
with your own, using the components {Object} prop. The object provided to the components prop
will be merged with Vue Select's default components.
<<< @/../src/components/childComponents.js{4-7}
You can override the value of any of these keys with your own components.
Deselect
You may wish to roll your own deselect button. Deselect is used within tags onmultiple selects, and serves as the clear button for single selects. Maybe you just want to use
a simple Clear instead.
<v-select :components="{Deselect}" />export default {
data: () => ({
Deselect: {
render: createElement => createElement('span', 'โ'),
},
}),
};The same approach applies for multiple selects:
OpenIndicator
The OpenIndicator component is the 'caret' used within the component that adjusts orientation
based on whether the dropdown is open or closed.
<v-select :components="{OpenIndicator}" />export default {
data: () => ({
selected: ['Canada'],
OpenIndicator: {
render: createElement => createElement('span', {class: {'toggle': true}}),
},
}),
};Setting Globally at Registration
If you want all instances of Vue Select to use your custom components throughout your app, while
only having to set the implementation once, you can do so when registering Vue Select as a component.
Vue 2x
import Vue from 'vue';
import vSelect from 'vue-select';
// Set the components prop default to return our fresh components
vSelect.props.components.default = () => ({
Deselect: {
render: createElement => createElement('span', 'โ'),
},
OpenIndicator: {
render: createElement => createElement('span', '๐ฝ'),
},
});
// Register the component
Vue.component(vSelect)Vue 3x
import {createApp, h} from 'vue';
import vSelect from 'vue-select';
// Set the components prop default to return our fresh components
vSelect.props.components.default = () => ({
Deselect: {
render: () => h('span', 'โ'),
},
OpenIndicator: {
render: () => h('span', '๐ฝ'),
},
});
// Register the component
const app = createApp(App);
app.component('vSelect', vSelect);File: docs/guide/css.md
Vue Select offers many APIs for customizing the look and feel from the component. You can use
scoped slots, custom child components, or modify the built in
CSS properties.
CSS Variables
Vue Select uses custom CSS properties throughout the component to handle visual opinions. This
allows for quite a bit of flexibility in styling, without having to hook into a build system for
generating your own styles with something like SASS. If there is a value that you think should use a
CSS property instead of a hardcoded CSS value, please submit a PR.
Dark Mode Example
Without writing any CSS yourself, you can completely customize the look and feel of Vue Select
through the use of CSS variables. In this example, we adjust the colors of the component to match
for a dark mode application.
In this case, the variables are scoped to only this implementation of the component, but you could
place these variables anywhere in your applications CSS file to implement at a global level for your
app.
Check the MDN docs for more info
about CSS Custom Properties.
<<< @/.vuepress/components/CssVariables.vue
Available CSS Variables 3.18+
<<< @/../src/css/global/variables.css
SCSS Deprecated in v3.18
::: warning Deprecation Notice
The SCSS build been deprecated for the v3.x release, and will be
removed in v4.0.0. The files will remain in the v3 codebase if you really need them, but the
recommended approach is to leverage the included CSS variables instead.
:::
Variables are leveraged in as much of the component styles as possible. If you really want to dig
into the SCSS, the files are located in src/scss. The variables listed below can be found atsrc/scss/global/_variables
.
All variables are implemented with !default in order to make them easier to override in your
application.
<<< @/../src/scss/global/_variables.scss
Overriding Default Styles
Vue Select takes the approach of using selectors with a single level of specificity, while using
classes that are very specific to Vue Select to avoid collisions with your app.
Most classes within Vue Select use the vs__ prefix, and selectors are generally a single classname
โ unless there is a state being applied to the component.
In order to override a default property in your app, you should add one level of specificity. The
easiest way to do this, is to add .v-select before the vs__* selector if you want to adjust all
instances of Vue Select, or add your own classname if you just want to affect one.
<<< @/.vuepress/components/CssSpecificity.vue
Dropdown Transition
By default, the dropdown transitions with a .15s cubic-bezier opacity fade in/out. The component
uses the VueJS transition system. By default, the
transition name is vs__fade. There's a couple ways to override or change this transition.
- Use the
transitionprop. Applying this prop will change the name of the animation classes and
negate the default CSS. If you want to remove it entirely, you can set it to an empty string.
<v-select transition="" />- You can also override the default CSS for the
vs__fadetransition. Again, if you wanted to
eliminate the transition entirely:
.vs__fade-enter-active,
.vs__fade-leave-active {
transition: none;
}File: docs/guide/examples.md
Codepen Collection
I've put together a collection of examples, including all the examples
from this documentation site on Codepen.
File: docs/guide/filtering.md
Vue Select provides two props accepting functions that can be used to implement custom filtering
algorithms.
filterfilterBy
By default, the component will perform a very basic check to see if an options label includes
the current search text. If you're using scoped slots, you might have information within the
option templates that should be searchable. Or maybe you just want a better search algorithm that
can do fuzzy search matching.
Filtering with Fuse.js
You can use the filter and filterBy props to hook right into something like
Fuse.js that can handle searching multiple object keys with fuzzy matchings.
<<< @/.vuepress/components/FuseFilter.vue
2. Official Technical Reference & Guides (sagalbot/docs)
File: README.md
Laravel Documentation
Contribution Guidelines
If you are submitting documentation for the current stable release, submit it to the corresponding branch. For example, documentation for Laravel 5.5 would be submitted to the 5.5 branch. Documentation intended for the next release of Laravel should be submitted to the master branch.
File: Readme.md
Laravel Documentation
Contribution Guidelines
If you are submitting documentation for the current stable release, submit it to the corresponding branch. For example, documentation for Laravel 5.5 would be submitted to the 5.5 branch. Documentation intended for the next release of Laravel should be submitted to the master branch.
File: readme.md
Laravel Documentation
Contribution Guidelines
If you are submitting documentation for the current stable release, submit it to the corresponding branch. For example, documentation for Laravel 5.5 would be submitted to the 5.5 branch. Documentation intended for the next release of Laravel should be submitted to the master branch.