2
0
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:
Jeff Sagal
2021-07-28 09:46:15 -07:00
parent 335920b586
commit 3399ecbd9a
86 changed files with 5656 additions and 4359 deletions
+134
View File
@@ -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);
```
+572
View File
@@ -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
},
```
+188
View File
@@ -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>
+64
View File
@@ -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). 🚧
+72
View File
@@ -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"/>
+83
View File
@@ -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 />
+58
View File
@@ -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;
}
```
+4
View File
@@ -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/#).
+19
View File
@@ -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
+23
View File
@@ -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
+60
View File
@@ -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.
+73
View File
@@ -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 noop 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
+45
View File
@@ -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).
+17
View File
@@ -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
View File
+54
View File
@@ -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 `[]`.
+18
View File
@@ -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
+33
View File
@@ -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}
+44
View File
@@ -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}
+32
View File
@@ -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
+119
View File
@@ -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
+24
View File
@@ -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>
```
+176
View File
@@ -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}`"
/>
```
+16
View File
@@ -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"/>