mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-19 09:50:33 +03:00
nuxt setup, tailwind
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
## `input`
|
||||
|
||||
Triggered when the selected value changes. Used internally for `v-model`.
|
||||
|
||||
```js
|
||||
/**
|
||||
* @param {Object|String} val - selected option.
|
||||
*/
|
||||
this.$emit("input", val);
|
||||
```
|
||||
|
||||
## `open`
|
||||
|
||||
Triggered when the dropdown is open.
|
||||
|
||||
```js
|
||||
this.$emit("open");
|
||||
```
|
||||
|
||||
## `close`
|
||||
|
||||
Triggered when the dropdown is closed.
|
||||
|
||||
```js
|
||||
this.$emit("close");
|
||||
```
|
||||
|
||||
## `option:selecting` <Badge text="v3.11.0+" />
|
||||
|
||||
Triggered after an option has been selected, <strong>before</strong> updating internal state.
|
||||
|
||||
```js
|
||||
this.$emit("option:selecting", selectedOption);
|
||||
```
|
||||
|
||||
## `option:selected` <Badge text="v3.11.0+" />
|
||||
|
||||
Triggered when an option has been selected, <strong>after</strong> updating internal state.
|
||||
|
||||
```js
|
||||
this.$emit("option:selected", selectedOption);
|
||||
```
|
||||
|
||||
## `option:deselecting` <Badge text="v3.11.0+" />
|
||||
|
||||
Triggered when an option has been deselected, <strong>before</strong> updating internal state.
|
||||
|
||||
```js
|
||||
this.$emit("option:deselecting", selectedOption);
|
||||
```
|
||||
|
||||
## `option:deselected` <Badge text="v3.11.0+" />
|
||||
|
||||
Triggered when an option has been deselected, <strong>after</strong> updating internal state.
|
||||
|
||||
```js
|
||||
this.$emit("option:deselected", deselectedOption);
|
||||
```
|
||||
|
||||
## `option:created`
|
||||
|
||||
Triggered when `taggable` is `true` and a new option has been created.
|
||||
|
||||
```js
|
||||
/**
|
||||
* @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](/guide/ajax.html#loading-options-with-ajax)
|
||||
for a complete example.
|
||||
|
||||
```js
|
||||
/**
|
||||
* @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);
|
||||
```
|
||||
|
||||
```vue
|
||||
<!-- example usage -->
|
||||
<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.
|
||||
|
||||
```js
|
||||
this.$emit("search:blur");
|
||||
```
|
||||
|
||||
## `search:focus`
|
||||
|
||||
Triggered when the text input gains focus. The dropdown will open immediately before this
|
||||
event is triggered.
|
||||
|
||||
```js
|
||||
this.$emit("search:focus");
|
||||
```
|
||||
|
||||
## `search`
|
||||
|
||||
Triggered when the search text changes.
|
||||
|
||||
```js
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @emits search
|
||||
*/
|
||||
this.$emit('search', newSearchString, toggleLoading);
|
||||
```
|
||||
|
||||
@@ -0,0 +1,572 @@
|
||||
## appendToBody <Badge text="v3.7.0+" />
|
||||
|
||||
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](../guide/positioning.md) for more details.
|
||||
|
||||
```js
|
||||
appendToBody: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## autocomplete
|
||||
|
||||
The value provided here will be bound to the [autocomplete
|
||||
HTML attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete)
|
||||
on the search input. Defaults to `off`.
|
||||
|
||||
```js
|
||||
autocomplete: {
|
||||
type: String,
|
||||
default: 'off'
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## autoscroll <Badge text="v3.10.0+" />
|
||||
|
||||
When true, the dropdown will automatically scroll to ensure
|
||||
that the option highlighted is fully within the dropdown viewport
|
||||
when navigating with keyboard arrows.
|
||||
|
||||
```js
|
||||
autoscroll: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## calculatePosition <Badge text="v3.7.0+" />
|
||||
|
||||
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](../guide/positioning.md) for more details.
|
||||
|
||||
```js
|
||||
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?
|
||||
|
||||
```js
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## clearSearchOnBlur
|
||||
|
||||
Enables/disables clearing the search text when the search input is blurred.
|
||||
|
||||
```js
|
||||
clearSearchOnBlur: {
|
||||
type: Function,
|
||||
default: function ({ clearSearchOnSelect, multiple }) {
|
||||
return clearSearchOnSelect && !multiple
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## clearSearchOnSelect
|
||||
|
||||
Enables/disables clearing the search text when an option is selected.
|
||||
|
||||
```js
|
||||
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)
|
||||
|
||||
```js
|
||||
closeOnSelect: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
## components <Badge text="v3.1.0+" />
|
||||
|
||||
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](../guide/components.md) for more details.
|
||||
|
||||
```js
|
||||
import Deselect from './Deselect';
|
||||
import OpenIndicator from './OpenIndicator';
|
||||
|
||||
// ...
|
||||
|
||||
components: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
Deselect,
|
||||
OpenIndicator
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## createOption
|
||||
|
||||
User defined function for adding Options
|
||||
|
||||
```js
|
||||
createOption: {
|
||||
type: Function,
|
||||
default(newOption) {
|
||||
if (typeof this.optionList[0] === 'object') {
|
||||
newOption = {[this.label]: newOption}
|
||||
}
|
||||
|
||||
this.$emit('option:created', newOption)
|
||||
return newOption
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## dir
|
||||
|
||||
Sets RTL support. Accepts `ltr`, `rtl`, `auto`.
|
||||
|
||||
```js
|
||||
dir: {
|
||||
type: String,
|
||||
default: "auto"
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## disabled
|
||||
|
||||
Disable the entire component.
|
||||
|
||||
```js
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
## dropdownShouldOpen <Badge text="v3.12.0+" />
|
||||
|
||||
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.
|
||||
|
||||
```js
|
||||
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.
|
||||
|
||||
```js
|
||||
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.
|
||||
|
||||
```js
|
||||
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.
|
||||
|
||||
```js
|
||||
filterBy: {
|
||||
type: Function,
|
||||
default(option, label, search) {
|
||||
return (label || '').toLowerCase().indexOf(search.toLowerCase()) > -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.
|
||||
|
||||
```js
|
||||
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` and
|
||||
`selected-option` slots.
|
||||
|
||||
```js
|
||||
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.
|
||||
|
||||
```js
|
||||
inputId: {
|
||||
type: String
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## label
|
||||
|
||||
Tells vue-select what key to use when generating option
|
||||
labels when each `option` is an object.
|
||||
|
||||
```js
|
||||
label: {
|
||||
type: String,
|
||||
default: "label"
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
```js
|
||||
maxHeight: {
|
||||
type: String,
|
||||
default: "400px"
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## multiple
|
||||
|
||||
Equivalent to the `multiple` attribute on a `<select>` input.
|
||||
|
||||
```js
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## noDrop
|
||||
|
||||
Disable the dropdown entirely.
|
||||
|
||||
```js
|
||||
noDrop: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## onTab
|
||||
|
||||
Select the current value if `selectOnTab` is enabled
|
||||
|
||||
```js
|
||||
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.
|
||||
|
||||
```js
|
||||
options: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## placeholder
|
||||
|
||||
Equivalent to the `placeholder` attribute on an `<input>`.
|
||||
|
||||
```js
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## pushTags
|
||||
|
||||
When true, newly created tags will be added to
|
||||
the options list.
|
||||
|
||||
```js
|
||||
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.
|
||||
|
||||
```js
|
||||
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.
|
||||
|
||||
```js
|
||||
/**
|
||||
* @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.
|
||||
|
||||
```js
|
||||
searchable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## selectable <Badge text="v3.3.0+" />
|
||||
|
||||
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.
|
||||
|
||||
```js
|
||||
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
|
||||
|
||||
```js
|
||||
selectOnTab: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## tabindex
|
||||
|
||||
Set the tabindex for the input field.
|
||||
|
||||
```js
|
||||
tabindex: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## taggable
|
||||
|
||||
Enable/disable creating options from searchInput.
|
||||
|
||||
```js
|
||||
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.
|
||||
|
||||
```js
|
||||
transition: {
|
||||
type: String,
|
||||
default: "fade"
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
## value
|
||||
|
||||
Contains the currently selected value. Very similar to a
|
||||
`value` attribute on an `<input>`. You can listen for changes
|
||||
using 'change' event using v-on.
|
||||
|
||||
```js
|
||||
value: {
|
||||
default: null
|
||||
},
|
||||
```
|
||||
@@ -0,0 +1,188 @@
|
||||
::: 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.
|
||||
:::
|
||||
|
||||
<style>
|
||||
.slot-docs h2 {
|
||||
border-top: 1px solid #f0f0f0;
|
||||
border-bottom: none;
|
||||
margin-top: 2rem;
|
||||
padding-top: 2rem;
|
||||
}
|
||||
.slot-docs h2:first-child {
|
||||
border-top: none;
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="slot-docs">
|
||||
|
||||
## `footer` <Badge text="3.8.0+" />
|
||||
|
||||
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 query
|
||||
- `loading {boolean}` - is the component loading
|
||||
- `searching {boolean}` - is the component searching
|
||||
- `filteredOptions {array}` - options filtered by the search text
|
||||
- `deselect {function}` - function to deselect an option
|
||||
|
||||
<SlotFooter />
|
||||
<<< @/.vuepress/components/SlotFooter.vue
|
||||
|
||||
## `header` <Badge text="3.8.0+" />
|
||||
|
||||
Displayed at the top of the component, above `.vs__dropdown-toggle`.
|
||||
|
||||
- `search {string}` - the current search query
|
||||
- `loading {boolean}` - is the component loading
|
||||
- `searching {boolean}` - is the component searching
|
||||
- `filteredOptions {array}` - options filtered by the search text
|
||||
- `deselect {function}` - function to deselect an option
|
||||
|
||||
<SlotHeader />
|
||||
<<< @/.vuepress/components/SlotHeader.vue
|
||||
|
||||
## `list-footer` <Badge text="3.8.0+" />
|
||||
|
||||
Displayed as the last item in the dropdown. No content by default. Parent element is the `<ul>`,
|
||||
so this slot should contain a root `<li>`.
|
||||
|
||||
- `search {string}` - the current search query
|
||||
- `loading {boolean}` - is the component loading
|
||||
- `searching {boolean}` - is the component searching
|
||||
- `filteredOptions {array}` - options filtered by the search text
|
||||
|
||||
<SlotListFooter />
|
||||
<<< @/.vuepress/components/SlotListFooter.vue
|
||||
|
||||
## `list-header` <Badge text="3.8.0+" />
|
||||
|
||||
Displayed as the first item in the dropdown. No content by default. Parent element is the `<ul>`,
|
||||
so this slot should contain a root `<li>`.
|
||||
|
||||
- `search {string}` - the current search query
|
||||
- `loading {boolean}` - is the component loading
|
||||
- `searching {boolean}` - is the component searching
|
||||
- `filteredOptions {array}` - options filtered by the search text
|
||||
|
||||
<SlotListHeader />
|
||||
<<< @/.vuepress/components/SlotListHeader.vue
|
||||
|
||||
## `no-options`
|
||||
|
||||
The no options slot is displayed above `list-footer` in the dropdown when
|
||||
`filteredOptions.length === 0`.
|
||||
|
||||
- `search {string}` - the current search query
|
||||
- `loading {boolean}` - is the component loading
|
||||
- `searching {boolean}` - is the component searching
|
||||
|
||||
<SlotNoOptions />
|
||||
<<< @/.vuepress/components/SlotNoOptions.vue
|
||||
|
||||
## `open-indicator`
|
||||
|
||||
The open indicator is the caret icon on the component used to indicate dropdown status.
|
||||
|
||||
```js
|
||||
attributes: {
|
||||
'ref': 'openIndicator',
|
||||
'role': 'presentation',
|
||||
'class': 'vs__open-indicator',
|
||||
}
|
||||
```
|
||||
|
||||
<SlotOpenIndicator />
|
||||
<<< @/.vuepress/components/SlotOpenIndicator.vue
|
||||
|
||||
## `option`
|
||||
|
||||
The current option within the dropdown, contained within `<li>`.
|
||||
|
||||
- `option {Object}` - The currently iterated option from `filteredOptions`
|
||||
|
||||
<SlotOption />
|
||||
<<< @/.vuepress/components/SlotOption.vue
|
||||
|
||||
## `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.
|
||||
|
||||
```js
|
||||
/**
|
||||
* 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,
|
||||
}
|
||||
```
|
||||
|
||||
<SlotSearch />
|
||||
<<< @/.vuepress/components/SlotSearch.vue{5-6}
|
||||
|
||||
## `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
|
||||
|
||||
<SlotSelectedOption />
|
||||
<<< @/.vuepress/components/SlotSelectedOption.vue
|
||||
|
||||
## `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 option
|
||||
- `deselect {Function}` - Method used to deselect a given option when `multiple` is true
|
||||
- `disabled {Boolean}` - Determine if the component is disabled
|
||||
- `multiple {Boolean}` - If the component supports the selection of multiple values
|
||||
|
||||
<SlotSelectedOptionContainer />
|
||||
<<< @/.vuepress/components/SlotSelectedOptionContainer.vue
|
||||
|
||||
## `spinner`
|
||||
|
||||
- `loading {Boolean}` - if the component is in a loading state
|
||||
|
||||
<SlotSpinner />
|
||||
<<< @/.vuepress/components/SlotSpinner.vue
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,64 @@
|
||||
Vue Select aims to follow the WAI-ARIA best practices for the
|
||||
[combobox](https://www.w3.org/TR/wai-aria-practices-1.1/#combobox) and
|
||||
[listbox](https://www.w3.org/TR/wai-aria-practices-1.1/#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
|
||||
|
||||
- [WAI-ARIA Combobox - Best Practices](https://www.w3.org/TR/wai-aria-practices-1.1/#combobox)
|
||||
- [WAI-ARIA Combobox - Specification](https://www.w3.org/TR/wai-aria-1.1/#combobox)
|
||||
|
||||
## Listbox
|
||||
|
||||
- [WAI-ARIA Listbox - Best Practices](https://www.w3.org/TR/wai-aria-practices-1.1/#Listbox)
|
||||
|
||||
### Autocomplete
|
||||
|
||||
WAI-ARIA suggests four forms of autocomplete for Comboboxes. Vue Select can be configured to provide
|
||||
these use cases.
|
||||
|
||||
1. **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']" />
|
||||
```
|
||||
<v-select :filterable="false" :options="['No Autocomplete', 'List Autocomplete']" />
|
||||
|
||||
2. **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']" />
|
||||
```
|
||||
<v-select taggable :options="['No Autocomplete', 'List Autocomplete']" />
|
||||
|
||||
3. **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']" />
|
||||
```
|
||||
<v-select :options="['No Autocomplete', 'List Autocomplete']" />
|
||||
|
||||
4. **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](https://github.com/sagalbot/vue-select/issues/865). 🚧
|
||||
@@ -0,0 +1,72 @@
|
||||
## 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 string
|
||||
- `loading {Function}` Accepts a boolean parameter to toggle the loading state
|
||||
|
||||
```html
|
||||
<v-select @search="fetchOptions" />
|
||||
```
|
||||
|
||||
```js
|
||||
/**
|
||||
* 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 the
|
||||
`loading` 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.
|
||||
|
||||
```js
|
||||
/**
|
||||
* 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. The
|
||||
`spinner` slot allows you to implement your own spinner.
|
||||
|
||||
```html
|
||||
<div class="spinner" v-show="spinner">Loading...</div>
|
||||
```
|
||||
|
||||
## 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](https://github.com/axios/axios) for creating your applications HTTP layer,
|
||||
or [`fetch()`](https://github.com/github/fetch) for simple requests.
|
||||
|
||||
## Example
|
||||
|
||||
The [codepen example](https://codepen.io/sagalbot/pen/POMeOX) wraps up all the above concepts and
|
||||
searches GitHub repositories. It also uses scoped slots to add some custom templating.
|
||||
|
||||
<CodePen url="POMeOX" height="400"/>
|
||||
@@ -0,0 +1,83 @@
|
||||
### 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 <Badge text="v3.1.0+" />
|
||||
|
||||
You may wish to roll your own deselect button. `Deselect` is used within tags on
|
||||
`multiple` selects, and serves as the clear button for single selects. Maybe you just want to use
|
||||
a simple `<button>Clear</button>` instead.
|
||||
|
||||
```html
|
||||
<v-select :components="{Deselect}" />
|
||||
```
|
||||
|
||||
```js
|
||||
export default {
|
||||
data: () => ({
|
||||
Deselect: {
|
||||
render: createElement => createElement('span', '❌'),
|
||||
},
|
||||
}),
|
||||
};
|
||||
```
|
||||
|
||||
<ClearButtonOverride />
|
||||
|
||||
The same approach applies for `multiple` selects:
|
||||
|
||||
<MultipleClearButtonOverride />
|
||||
|
||||
## OpenIndicator <Badge text="v3.1.0+" />
|
||||
|
||||
The `OpenIndicator` component is the 'caret' used within the component that adjusts orientation
|
||||
based on whether the dropdown is open or closed.
|
||||
|
||||
```html
|
||||
<v-select :components="{OpenIndicator}" />
|
||||
```
|
||||
```js
|
||||
export default {
|
||||
data: () => ({
|
||||
selected: ['Canada'],
|
||||
OpenIndicator: {
|
||||
render: createElement => createElement('span', {class: {'toggle': true}}),
|
||||
},
|
||||
}),
|
||||
};
|
||||
```
|
||||
|
||||
<OpenIndicatorOverride />
|
||||
|
||||
## 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.
|
||||
|
||||
```js
|
||||
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)
|
||||
```
|
||||
|
||||
<CustomComponentRegistration />
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
Vue Select offers many APIs for customizing the look and feel from the component. You can use
|
||||
[scoped slots](../api/slots.md), [custom child components](components.md), or modify the built in
|
||||
SCSS variables.
|
||||
|
||||
::: tip
|
||||
Support for CSS variables (custom properties) is currently on the road map for those
|
||||
that are not using sass in their projects.
|
||||
:::
|
||||
|
||||
## SCSS Variables
|
||||
|
||||
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 at
|
||||
[`src/scss/global/_variables`](https://github.com/sagalbot/vue-select/blob/master/src/scss/global/_variables.scss).
|
||||
|
||||
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.
|
||||
|
||||
All 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.
|
||||
|
||||
<CssSpecificity />
|
||||
|
||||
<<< @/.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](https://vuejs.org/v2/guide/transitions.html). By default, the
|
||||
transition name is `vs__fade`. There's a couple ways to override or change this transition.
|
||||
|
||||
1. Use the `transition` prop. 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.
|
||||
|
||||
```html
|
||||
<v-select transition="" />
|
||||
```
|
||||
|
||||
2. You can also override the default CSS for the `vs__fade` transition. Again, if you
|
||||
wanted to eliminate the transition entirely:
|
||||
|
||||
```css
|
||||
.vs__fade-enter-active,
|
||||
.vs__fade-leave-active {
|
||||
transition: none;
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,4 @@
|
||||
### Codepen Collection
|
||||
|
||||
I've put together a collection of examples, including all the examples
|
||||
from this documentation site on [Codepen](https://codepen.io/collection/nrkgxV/#).
|
||||
@@ -0,0 +1,19 @@
|
||||
Vue Select provides two props accepting `functions` that can be used to implement custom filtering
|
||||
algorithms.
|
||||
|
||||
- `filter` <Badge text="v2.5.0+" />
|
||||
- `filterBy` <Badge text="v2.5.0+" />
|
||||
|
||||
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](https://fusejs.io/) that can handle searching multiple object keys with fuzzy matchings.
|
||||
|
||||
<FuseFilter />
|
||||
|
||||
<<< @/.vuepress/components/FuseFilter.vue
|
||||
@@ -0,0 +1,23 @@
|
||||
Vue Select doesn't ship with first party support for infinite scroll, but it's possible to implement
|
||||
by hooking into the `open`, `close`, and `search` events, along with the `filterable` prop, and the
|
||||
`list-footer` slot.
|
||||
|
||||
Let's break down the example below, starting with the `data`.
|
||||
|
||||
- `observer` - a new `IntersectionObserver` with `infiniteScroll` set as the callback
|
||||
- `limit` - the number of options to display
|
||||
- `search` - since we've disabled Vue Selects filtering, we'll need to filter options ourselves
|
||||
|
||||
When Vue Select opens, the `open` event is emitted and `onOpen` will be called. We wait for
|
||||
`$nextTick()` so that the `$ref` we need will exist, then begin observing it for intersection.
|
||||
|
||||
The observer is set to call `infiniteScroll` when the `<li>` is completely visible within the list.
|
||||
Some fancy destructuring is done here to get the first `ObservedEntry`, and specifically the
|
||||
`isIntersecting` & `target` properties. If the `<li>` is intersecting, we increase the `limit`, and
|
||||
ensure that the scroll position remains where it was before the list size changed. Again, it's
|
||||
important to wait for `$nextTick` here so that the DOM elements have been inserted before setting
|
||||
the scroll position.
|
||||
|
||||
<InfiniteScroll />
|
||||
|
||||
<<< @/.vuepress/components/InfiniteScroll.vue
|
||||
@@ -0,0 +1,60 @@
|
||||
## Yarn / NPM
|
||||
Install with yarn:
|
||||
```bash
|
||||
yarn add vue-select
|
||||
|
||||
# or, using NPM
|
||||
npm install vue-select
|
||||
```
|
||||
|
||||
Then, import and register the component:
|
||||
|
||||
```js
|
||||
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:
|
||||
|
||||
```js
|
||||
import 'vue-select/dist/vue-select.css';
|
||||
```
|
||||
|
||||
Alternatively, you can import the scss for complete control of the component styles:
|
||||
|
||||
```scss
|
||||
@import "vue-select/src/scss/vue-select.scss";
|
||||
```
|
||||
|
||||
## In the Browser
|
||||
|
||||
vue-select ships as an UMD module that is accessible in the browser. When loaded
|
||||
in the browser, you can access the component through the `VueSelect.VueSelect`
|
||||
global variable. You'll need to load Vue.js, vue-select JS & vue-select CSS.
|
||||
|
||||
```html
|
||||
<!-- include VueJS first -->
|
||||
<script src="https://unpkg.com/vue@latest"></script>
|
||||
|
||||
<!-- use the latest vue-select release -->
|
||||
<script src="https://unpkg.com/vue-select@latest"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/vue-select@latest/dist/vue-select.css">
|
||||
|
||||
<!-- or point to a specific vue-select release -->
|
||||
<script src="https://unpkg.com/vue-select@3.0.0"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/vue-select@3.0.0/dist/vue-select.css">
|
||||
```
|
||||
Then register the component in your javascript:
|
||||
|
||||
```js
|
||||
Vue.component('v-select', VueSelect.VueSelect);
|
||||
```
|
||||
|
||||
<CodePen url="dJjzeP" />
|
||||
|
||||
## Vue Compatibility
|
||||
|
||||
- If you're on Vue `1.x`, use vue-select `1.x`.
|
||||
- The `1.x` branch has not received updates since the 2.0 release.
|
||||
@@ -0,0 +1,73 @@
|
||||
### Customizing Keydown Behaviour
|
||||
---
|
||||
|
||||
## selectOnKeyCodes <Badge text="v3.3.0+" />
|
||||
|
||||
`selectOnKeyCodes {Array}` is an array of keyCodes that will trigger a typeAheadSelect. Any keyCodes
|
||||
in this array will prevent the default event action and trigger a typeahead select. By default,
|
||||
it's just `[13]` for return. For example, maybe you want to tag on a comma keystroke:
|
||||
|
||||
<TagOnComma />
|
||||
|
||||
<<< @/.vuepress/components/TagOnComma.vue
|
||||
|
||||
## mapKeyDown <Badge text="v3.3.0+" />
|
||||
|
||||
Vue Select provides the `map-keydown` Function prop to allow for customizing the components response to
|
||||
keydown events while the search input has focus.
|
||||
|
||||
```js
|
||||
/**
|
||||
* @param map {Object} Mapped keyCode to handlers { <keyCode>:<callback> }
|
||||
* @param vm {VueSelect}
|
||||
* @return {Object}
|
||||
*/
|
||||
(map, vm) => map,
|
||||
```
|
||||
|
||||
By default, the prop is a no–op returning the same object `map` object it receives. This object
|
||||
maps keyCodes to handlers: `{ <keyCode>: <callback> }`. Modifying this object can override default
|
||||
functionality, or add handlers for different keys that the component doesn't normally listen for.
|
||||
|
||||
Note that any keyCodes you've added to `selectOnKeyCodes` will be passed to `map-keydown` as well,
|
||||
so `map-keydown` will always take precedence.
|
||||
|
||||
**Default Handlers**
|
||||
|
||||
```js
|
||||
// delete
|
||||
8: e => this.maybeDeleteValue()
|
||||
|
||||
// tab
|
||||
9: e => this.onTab()
|
||||
|
||||
// enter
|
||||
13: e => {
|
||||
e.preventDefault();
|
||||
return this.typeAheadSelect();
|
||||
}
|
||||
|
||||
// esc
|
||||
27: e => this.onEscape()
|
||||
|
||||
// up
|
||||
38: e => {
|
||||
e.preventDefault();
|
||||
return this.typeAheadUp();
|
||||
}
|
||||
|
||||
// down
|
||||
40: e => {
|
||||
e.preventDefault();
|
||||
return this.typeAheadDown();
|
||||
}
|
||||
```
|
||||
|
||||
### Example: Autocomplete Email Addresses
|
||||
|
||||
This is example listens for the `@` key, and autocompletes an email address with `@gmail.com`.
|
||||
|
||||
<CustomHandlers />
|
||||
|
||||
<<< @/.vuepress/components/CustomHandlers.vue
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
## Right to Left
|
||||
|
||||
Vue Select supports RTL using the standard HTML API using the `dir` prop.
|
||||
|
||||
```html
|
||||
<v-select dir="rtl"></v-select>
|
||||
```
|
||||
|
||||
The `dir` prop accepts the same values as the [HTML spec](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir):
|
||||
|
||||
- `rtl`
|
||||
- `ltr`
|
||||
- `auto`
|
||||
|
||||
## Component Text
|
||||
|
||||
All of the text within the component has been wrapped within [slots](https://vuejs.org/v2/guide/components.html#Content-Distribution-with-Slots) and can be replaced in your app.
|
||||
|
||||
### Loading Spinner
|
||||
*Slot Definition:*
|
||||
```html
|
||||
<slot name="spinner">
|
||||
<div class="spinner" v-show="mutableLoading">Loading...</div>
|
||||
</slot>
|
||||
```
|
||||
*Implementation:*
|
||||
```html
|
||||
<v-select>
|
||||
<i slot="spinner" class="icon icon-spinner"></i>
|
||||
</v-select>
|
||||
```
|
||||
|
||||
### No Options Text
|
||||
*Slot Definition:*
|
||||
```html
|
||||
<slot name="no-options">Sorry, no matching options.</slot>
|
||||
```
|
||||
*Implementation:*
|
||||
```html
|
||||
<v-select>
|
||||
<div slot="no-options">No Options Here!</div>
|
||||
</v-select>
|
||||
```
|
||||
|
||||
For a full list of component slots, view the [slots API docs](../api/slots.md).
|
||||
@@ -0,0 +1,17 @@
|
||||
### Using Vue Select in v-for Loops
|
||||
---
|
||||
|
||||
There may be times that you are including Vue Select within loops of data, such as a table. This can
|
||||
pose some challenges when emitting events from the component, as you won't know which Vue Select
|
||||
instance emitted it. This can make it difficult to wire up with things like Vuex.
|
||||
|
||||
Fortunately, you can solve this problem with an anonymous function. The example below doesn't use
|
||||
Vuex just to keep things succinct, but the same solution would apply. The `@input` is handled
|
||||
with an inline anonymous function, allowing the selected country to be passed to the `updateCountry`
|
||||
method with the `country` and the `person` object.
|
||||
|
||||
<LoopedSelect />
|
||||
|
||||
<<< @/.vuepress/components/LoopedSelect.vue
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
## Options Prop
|
||||
|
||||
`vue-select` accepts arrays of primitive values or objects to use as options through the `options` prop:
|
||||
|
||||
```html
|
||||
<!-- array of strings or numbers -->
|
||||
<v-select :options="['Canada', 'United States']"></v-select>
|
||||
```
|
||||
|
||||
<v-select :options="['Canada', 'United States']"></v-select>
|
||||
|
||||
```html
|
||||
<!-- or, an array of objects -->
|
||||
<v-select :options="[{label: 'Canada', code: 'ca'}]"></v-select>
|
||||
```
|
||||
|
||||
<v-select :options="[{label: 'Canada', code: 'ca'}]"></v-select>
|
||||
|
||||
## Option Labels
|
||||
|
||||
#### Options as Primitives (strings, numbers, boolean)
|
||||
|
||||
When `options` contains strings or numbers, they'll be used as the label for the option within the
|
||||
component. No further configuration is necessary.
|
||||
|
||||
#### Options as Objects
|
||||
|
||||
When `options` is an array of objects, the component must generate a label to be shown as the
|
||||
options text. By default, `vue-select` will attempt to render `option.label` as the option label.
|
||||
You might not have a `label` key in your objects, so you can set your own label to match your
|
||||
source data using the `label {String}` prop.
|
||||
|
||||
For example, consider an object with `countryCode` and `countryName` properties:
|
||||
|
||||
```json
|
||||
{
|
||||
countryCode: "CA",
|
||||
countryName: "Canada"
|
||||
}
|
||||
```
|
||||
|
||||
If you wanted to display `Canada` in the dropdown, you'd use the `countryName` key:
|
||||
|
||||
```html
|
||||
<v-select label="countryName" :options="countries"></v-select>
|
||||
```
|
||||
|
||||
<country-select />
|
||||
|
||||
## Null / Empty Options
|
||||
|
||||
`vue-select` requires the `options` prop to be an `array`. If you are using Vue in development
|
||||
mode, you will get warnings attempting to pass anything other than an `array` to the `options` prop.
|
||||
If you need a `null`/`empty` value, use an empty array `[]`.
|
||||
@@ -0,0 +1,18 @@
|
||||
::: tip <Badge text="3.8.0+" />
|
||||
Pagination is supported using slots available with Vue Select 3.8 and above.
|
||||
:::
|
||||
|
||||
Pagination can be a super helpful tool when working with large sets of data. If you have 1,000
|
||||
options, the component is going to render 1,000 DOM nodes. That's a lot of nodes to insert/remove,
|
||||
and chances are your user is only interested in a few of them anyways.
|
||||
|
||||
To implement pagination with Vue Select, you can take advantage of the `list-footer` slot. It
|
||||
appears below all other options in the drop down list.
|
||||
|
||||
To make pagination work properly with filtering, you'll have to handle it yourself in the parent.
|
||||
You can use the `filterable` boolean to turn off Vue Select's filtering, and then hook into the
|
||||
`search` event to use the current search query in the parent component.
|
||||
|
||||
<Paginated />
|
||||
|
||||
<<< @/.vuepress/components/Paginated.vue
|
||||
@@ -0,0 +1,33 @@
|
||||
## Default
|
||||
|
||||
With the default CSS, Vue Select uses absolute positioning to render the dropdown menu. The root
|
||||
`.v-select` container (the components `$el`) is used as the `relative` parent for the dropdown. The
|
||||
dropdown will be displayed below the `$el` regardless of the available space.
|
||||
|
||||
This works for most cases, but you might run into issues placing into a modal or near the bottom of
|
||||
the viewport. If you need more fine grain control, you can use calculated positioning.
|
||||
|
||||
## Calculated <Badge text="v3.7.0+" />
|
||||
|
||||
If you want more control over how the dropdown is rendered, or if you're running into z-index issues,
|
||||
you may use the `appendToBody` boolean prop. When enabled, Vue Select will append the dropdown to
|
||||
the document, outside of the `.v-select` container, and position it with Javscript.
|
||||
|
||||
When `appendToBody` is true, the positioning will be handled by the `calculatePosition` prop. This
|
||||
function is responsible for setting top/left absolute positioning values for the dropdown. The
|
||||
default implementation places the dropdown in the same position that it would normally appear.
|
||||
|
||||
## Popper.js Integration <Badge text="v3.7.0+" />
|
||||
|
||||
[Popper.js](https://popper.js.org/) is an awesome, 3kb utility for calculating positions of just
|
||||
about any DOM element relative to another.
|
||||
|
||||
By using the `appendToBody` and `calculatePosition` props, we're able to integrate directly with
|
||||
popper to calculate positioning for us.
|
||||
|
||||
<PositionedWithPopper />
|
||||
|
||||
Check out the [Popper Docs](https://popper.js.org/docs/v2/modifiers/) to see the full `modifiers`
|
||||
API being used below.
|
||||
|
||||
<<< @/.vuepress/components/PositionedWithPopper.vue{25-59}
|
||||
@@ -0,0 +1,44 @@
|
||||
## Selectable Prop <Badge text="v3.3.0+" />
|
||||
|
||||
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.
|
||||
|
||||
```js
|
||||
selectable: {
|
||||
type: Function,
|
||||
/**
|
||||
* @param {Object|String} option
|
||||
* @return {boolean}
|
||||
*/
|
||||
default: option => true,
|
||||
},
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
Here `selectable` is used to prevent books by a certain author from being chosen. In this case,
|
||||
the options passed to the component are objects:
|
||||
|
||||
```json
|
||||
{
|
||||
title: "Right Ho Jeeves",
|
||||
author: { firstName: "P.D", lastName: "Woodhouse" },
|
||||
}
|
||||
```
|
||||
|
||||
This object will be passed to `selectable`, so we can check if the author should be selectable or not.
|
||||
|
||||
<UnselectableExample />
|
||||
|
||||
<<< @/.vuepress/components/UnselectableExample.vue{6}
|
||||
|
||||
## Limiting the Number of Selections
|
||||
|
||||
`selectable` can also be used a bit more creatively to limit the number selections that can be made
|
||||
within the component. In this case, the user can select any author, but may only select a maximum
|
||||
of three books.
|
||||
|
||||
<LimitSelectionQuantity />
|
||||
|
||||
<<< @/.vuepress/components/LimitSelectionQuantity.vue{8}
|
||||
@@ -0,0 +1,32 @@
|
||||
::: tip 🚧
|
||||
This section of the guide is a work in progress! Check back soon for an update.
|
||||
Vue Select currently offers quite a few scoped slots, and you can check out the
|
||||
[API Docs for Slots](../api/slots.md) in the meantime while a good guide is put together.
|
||||
:::
|
||||
|
||||
### Scoped Slot `option`
|
||||
|
||||
vue-select provides the scoped `option` slot in order to create custom dropdown templates.
|
||||
|
||||
```html
|
||||
<v-select :options="options" label="title">
|
||||
<template v-slot:option="option">
|
||||
<span :class="option.icon"></span>
|
||||
{{ option.title }}
|
||||
</template>
|
||||
</v-select>
|
||||
```
|
||||
|
||||
Using the `option` slot with props `"option"` provides the current option variable to the template.
|
||||
|
||||
<CodePen url="NXBwYG" height="500"/>
|
||||
|
||||
### Improving the default `no-options` text
|
||||
|
||||
The `no-options` slot is displayed in the dropdown when `filteredOptions === 0`. By default, it
|
||||
displays _Sorry, no matching options_. You can add more contextual information by using the slot
|
||||
in your own apps.
|
||||
|
||||
<BetterNoOptions />
|
||||
|
||||
<<< @/.vuepress/components/BetterNoOptions.vue
|
||||
@@ -0,0 +1,119 @@
|
||||
## `index` prop replaced with `reduce`
|
||||
|
||||
- v2.x provided the `index` `{String}` prop to return a single key from a selected object
|
||||
- v3.x removes the `index` prop, replacing it with the `reduce` `{Function}` prop.
|
||||
|
||||
Using a function instead of a string provides a whole lot more flexibility, allowing for things like
|
||||
deeply nested values, and really cleaned up the code internally.
|
||||
|
||||
```js
|
||||
const options = [{country: 'Canada', code: 'CA'},];
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- v2: using index --->
|
||||
<v-select :options="options" label="country" index="code" />
|
||||
|
||||
<!-- v3: using reduce --->
|
||||
<v-select :options="options" label="country" :reduce="country => country.code" />
|
||||
```
|
||||
|
||||
View the full [documentation for `reduce`](values.md#returning-a-single-key-with-reduce).
|
||||
|
||||
## Events instead of Callbacks
|
||||
|
||||
Three function callbacks have been removed in favor of using events.
|
||||
|
||||
- `onChange`
|
||||
- `onInput`
|
||||
- `onSearch`
|
||||
|
||||
While this is a breaking change, the change in your application should be as simple as swapping the
|
||||
prop you were using for an event.
|
||||
|
||||
### `onChange` & `onInput`
|
||||
|
||||
In v2.x, Overwriting `onChange` in an application was more likely to break vue-select's internals
|
||||
and cause issues. The `input` event provides identical functionality and can be swapped out in your
|
||||
application.
|
||||
|
||||
```html
|
||||
<!-- version 2: -->
|
||||
<v-select :on-change="doSomething" />
|
||||
|
||||
<!-- version 3: -->
|
||||
<v-select @input="doSomething" />
|
||||
```
|
||||
|
||||
Additionally, the `change` event has been removed. This event was redundant, `input` should be used
|
||||
instead.
|
||||
|
||||
```html
|
||||
<!-- version 2: -->
|
||||
<v-select @change="doSomething" />
|
||||
|
||||
<!-- version 3: -->
|
||||
<v-select @input="doSomething" />
|
||||
```
|
||||
|
||||
### `onSearch`
|
||||
|
||||
The `onSearch` prop was removed for the same reason as `onChange` and `onInput`. The `search` event
|
||||
has always provided the same parameters and can be used in it's place.
|
||||
|
||||
```html
|
||||
<!-- version 2: -->
|
||||
<v-select :on-search="doSomeAjax" />
|
||||
|
||||
<!-- version 3: -->
|
||||
<v-select @search="doSomeAjax" />
|
||||
```
|
||||
|
||||
### `@search` with null search string
|
||||
|
||||
The `@search` event is now fired anytime the search string changes. In v2.x, the component
|
||||
would first check if the search string was empty, and only emit the event if it had at least one
|
||||
character. This was a design mistake, as it should be the consumers decision if a search should be
|
||||
run on an empty string.
|
||||
|
||||
## Separated CSS
|
||||
|
||||
CSS was removed from the JS bundle in favor of a separate CSS file to support SSR and easier
|
||||
customization.
|
||||
|
||||
```js
|
||||
@import vSelect from 'vue-select`;
|
||||
@import 'vue-select/dist/vue-select.css';
|
||||
```
|
||||
|
||||
## New Class Selector Prefix
|
||||
|
||||
In order to avoid CSS collisions and allow for low specificity overrides of CSS, all classes have
|
||||
been renamed to include the `vs__` prefix. The full list of renamed classes are listed below:
|
||||
|
||||
| original | renamed |
|
||||
| ------- | --------- |
|
||||
| `.open-indicator` | `.vs__open-indicator` |
|
||||
| `.dropdown-toggle` | `.vs__dropdown-toggle` |
|
||||
| `.dropdown-menu` | `.vs__dropdown-menu` |
|
||||
| `.clear` | `.vs__clear` |
|
||||
| `.selected-tag` | `.vs__selected` |
|
||||
| `.no-options` | `.vs__no-options` |
|
||||
| `.spinner` | `.vs__spinner` |
|
||||
| `.close` | `.vs__deselect` |
|
||||
| `.active` | `.vs__active` |
|
||||
|
||||
## Internal State
|
||||
|
||||
**The changes listed below are very unlikely to break your apps** unless you've been hooking into
|
||||
vue-select internal values. [#781](https://github.com/sagalbot/vue-select/pull/781)
|
||||
(thanks [@owenconti!](https://github.com/owenconti)) introduced a number of optimizations to the
|
||||
way that the component handles internal state.
|
||||
|
||||
- `value`: the `value` prop is undefined by default. vue-select no longer maintains an internal `mutableValue` state when a `value` prop has been passed. When `:value` or `v-model` is not used, vue-select will maintain internal state using the `_value` property.
|
||||
- `mutableOptions` has been removed in favor of an `optionList` computed property.
|
||||
|
||||
## Misc
|
||||
|
||||
- `fade` transition renamed to `vs__fade`
|
||||
- Removed `a` element that was serving as the click handler within dropdown options
|
||||
@@ -0,0 +1,24 @@
|
||||
## Required
|
||||
|
||||
If you need to ensure that a selection is made before a form is submitted, you can
|
||||
use the `required` attribute in combination with the `search` scoped slot in order
|
||||
to do so.
|
||||
|
||||
However, the `search` input within the component does not actually store a value, so
|
||||
simply adding the `required` attribute won't work. Instead, we'll bind the attribute
|
||||
dynamically, so that it's only present if we don't have a selection.
|
||||
|
||||
<ValidationRequired />
|
||||
|
||||
```html
|
||||
<v-select :options="books" label="title" v-model="selected">
|
||||
<template #search="{attributes, events}">
|
||||
<input
|
||||
class="vs__search"
|
||||
:required="!selected"
|
||||
v-bind="attributes"
|
||||
v-on="events"
|
||||
/>
|
||||
</template>
|
||||
</v-select>
|
||||
```
|
||||
@@ -0,0 +1,176 @@
|
||||
## Getting and Setting
|
||||
|
||||
### `v-model`
|
||||
|
||||
The most common use case for vue-select is to have the chosen value synced with a parent component. vue-select
|
||||
takes advantage of the `v-model` syntax to sync values with a parent. The `v-model` syntax works with
|
||||
primitives and objects.
|
||||
|
||||
```html
|
||||
<v-select v-model="selected" />
|
||||
```
|
||||
|
||||
Note that when using the `multiple` prop, the `v-model` value will always be an array.
|
||||
|
||||
### Props and Events
|
||||
|
||||
Sometimes `v-model` might not fit your use case. For example, when working with [Vuex](https://vuex.vuejs.org),
|
||||
you'll need to trigger a mutation rather than mutating a value directly. In that case, maybe you need
|
||||
to bind a pre-selected value, and trigger a mutation when it changes.
|
||||
|
||||
vue-select exposes the `value` prop and an `input` event to enable this. This combo of props and
|
||||
events is also how Vue wires up the `v-model` syntax internally.
|
||||
|
||||
#### Prop: `value`
|
||||
|
||||
The `value` prop lets vue-select know what value is currently selected. It will accept strings,
|
||||
numbers or objects. If you're using a `multiple` v-select, you'll want to pass an array.
|
||||
|
||||
```html
|
||||
<v-select :value="selected" />
|
||||
```
|
||||
|
||||
::: tip 🤓
|
||||
Anytime you bind the `value` prop directly, you're responsible for updating the bound variable
|
||||
in your code using the `@input` event.
|
||||
:::
|
||||
|
||||
#### Event: `input`
|
||||
|
||||
The `input` event is triggered anytime the value state changes, and is emitted with the `value`
|
||||
state as it's only parameter.
|
||||
|
||||
#### Vuex Support
|
||||
|
||||
The `value` prop and `emit` event are very useful when using a state management tool, like Vuex.
|
||||
You can bind the selected value with `:value="$store.myValue"`, and use the `input` event to
|
||||
trigger a mutation, or dispatch an action – or anything else you might need to do when the selection
|
||||
changes.
|
||||
|
||||
```html
|
||||
<v-select :value="$store.myValue" @input="setSelected" />
|
||||
```
|
||||
|
||||
```js
|
||||
methods: {
|
||||
setSelected(value) {
|
||||
// trigger a mutation, or dispatch an action
|
||||
}
|
||||
}
|
||||
```
|
||||
## Transforming Selections
|
||||
|
||||
When the `options` array contains objects, vue-select returns the whole object as dropdown value
|
||||
upon selection. This approach makes no assumptions about the data you need, and provides a lot of
|
||||
flexibility. However, there will be situations where maybe you just need to return a single key
|
||||
from an object.
|
||||
|
||||
### Returning a single key with `reduce`
|
||||
|
||||
If you need to return a single key, or transform the selection before it is synced, vue-select
|
||||
provides a `reduce` callback that allows you to transform a selected option before it is passed to
|
||||
the `@input` event. Consider this data structure:
|
||||
|
||||
```js
|
||||
let options = [{code: 'CA', country: 'Canada'}];
|
||||
```
|
||||
|
||||
If we want to display the `country`, but return the `code` to `v-model`, we can use the `reduce`
|
||||
prop to receive only the data that's required.
|
||||
|
||||
```html
|
||||
<v-select :options="options" :reduce="country => country.code" label="country" />
|
||||
```
|
||||
|
||||
### Deep Nested Values
|
||||
|
||||
The `reduce` property also works well when you have a deeply nested value:
|
||||
|
||||
```
|
||||
{
|
||||
country: 'canada',
|
||||
meta: {
|
||||
code: 'ca'
|
||||
provinces: [...],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<v-select :options="options" :reduce="country => country.meta.code" label="country" />
|
||||
```
|
||||
|
||||
<reducer-nested-value />
|
||||
|
||||
## Single/Multiple Selection
|
||||
|
||||
By default, vue-select supports choosing a single value. If you need multiple values, use the
|
||||
`multiple` boolean prop, much the same way you would on an HTML `<select>` element. When `multiple`
|
||||
is true, `v-model` and `value` must be an array.
|
||||
|
||||
|
||||
```html
|
||||
<v-select multiple v-model="selected" :options="['Canada','United States']" />
|
||||
```
|
||||
<v-select multiple :options="['Canada','United States']" />
|
||||
|
||||
## Tagging
|
||||
|
||||
To allow input that's not present within the options, set the `taggable` prop to true.
|
||||
|
||||
```html
|
||||
<v-select taggable multiple />
|
||||
```
|
||||
|
||||
<v-select taggable multiple />
|
||||
|
||||
If you want added tags to be pushed to the options array, set `push-tags` to true.
|
||||
|
||||
```html
|
||||
<v-select taggable multiple push-tags />
|
||||
```
|
||||
|
||||
<v-select taggable multiple push-tags />
|
||||
|
||||
### Using `taggable` & `reduce` together
|
||||
|
||||
When combining `taggable` with `reduce`, you must define the `createOption` prop. The
|
||||
`createOption` function is responsible for defining the structure of the objects that Vue Select
|
||||
will create for you when adding a tag. It should return a value that has the same properties as the
|
||||
rest of your `options`.
|
||||
|
||||
If you don't define `createOption`, Vue Select will construct a simple object following this structure:
|
||||
`{[this.label]: searchText}`. If you're using `reduce`, this is probably not what your options look
|
||||
like, which is why you'll need to set the function yourself.
|
||||
|
||||
**Example**
|
||||
|
||||
We have a taggable select for adding books to a collection. We're just concerned about getting the
|
||||
book title added, and our server side code will add the author details in a background process. The
|
||||
user has already selected a book.
|
||||
|
||||
```js
|
||||
const options = [
|
||||
{
|
||||
title: "HTML5",
|
||||
author: {
|
||||
firstName: "Remy",
|
||||
lastName: "Sharp"
|
||||
}
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
```html
|
||||
<v-select
|
||||
taggable
|
||||
multiple
|
||||
label="title"
|
||||
:options="options"
|
||||
:create-option="book => ({ title: book, author: { firstName: '', lastName: '' } })"
|
||||
:reduce="book => `${book.author.firstName} ${book.author.lastName}`"
|
||||
/>
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
### Using the `input` Event with Vuex
|
||||
|
||||
`vue-select` emits the `input` event any time the internal `value` is changed.
|
||||
This is the same event that allow the for the `v-model` syntax. When using
|
||||
Vuex for state management, you can use the `input` event to dispatch an
|
||||
action, or trigger a mutation.
|
||||
|
||||
```html
|
||||
<v-select
|
||||
@input="myAction"
|
||||
:options="$store.state.options"
|
||||
:value="$store.state.selected"
|
||||
></v-select>
|
||||
```
|
||||
|
||||
<CodePen url="aJQJyp" height="350"/>
|
||||
Reference in New Issue
Block a user