2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-22 10:30:34 +03:00

docs: add reduce caveats

This commit is contained in:
Jeff Sagal
2021-10-22 17:17:18 -07:00
parent 5a6c9bf707
commit 0d294c31bd
2 changed files with 112 additions and 59 deletions
@@ -0,0 +1,20 @@
<template>
<v-select
v-model="selected"
:reduce="(option) => option.id"
:options="[
{ label: 'One', id: 1 },
{ label: 'Two', id: 2 },
]"
/>
</template>
<script>
export default {
data() {
return {
selected: 3,
}
},
}
</script>
+92 -59
View File
@@ -2,11 +2,12 @@
### `v-model` ### `v-model`
The most common use case for vue-select is to have the chosen value synced with a parent component. vue-select The most common use case for vue-select is to have the chosen value synced with a parent component.
takes advantage of the `v-model` syntax to sync values with a parent. The `v-model` syntax works with vue-select takes advantage of the `v-model` syntax to sync values with a parent. The `v-model`
primitives and objects. syntax works with primitives and objects.
```html ```html
<v-select v-model="selected" /> <v-select v-model="selected" />
``` ```
@@ -14,25 +15,26 @@ Note that when using the `multiple` prop, the `v-model` value will always be an
### Props and Events ### Props and Events
Sometimes `v-model` might not fit your use case. For example, when working with [Vuex](https://vuex.vuejs.org), Sometimes `v-model` might not fit your use case. For example, when working
you'll need to trigger a mutation rather than mutating a value directly. In that case, maybe you need with [Vuex](https://vuex.vuejs.org), you'll need to trigger a mutation rather than mutating a value
to bind a pre-selected value, and trigger a mutation when it changes. 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 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. events is also how Vue wires up the `v-model` syntax internally.
#### Prop: `value` #### Prop: `value`
The `value` prop lets vue-select know what value is currently selected. It will accept strings, 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. numbers or objects. If you're using a `multiple` v-select, you'll want to pass an array.
```html ```html
<v-select :value="selected" /> <v-select :value="selected" />
``` ```
::: tip 🤓 ::: tip 🤓 Anytime you bind the `value` prop directly, you're responsible for updating the bound
Anytime you bind the `value` prop directly, you're responsible for updating the bound variable variable in your code using the `@input` event.
in your code using the `@input` event.
::: :::
#### Event: `input` #### Event: `input`
@@ -42,50 +44,66 @@ state as it's only parameter.
#### Vuex Support #### Vuex Support
The `value` prop and `emit` event are very useful when using a state management tool, like Vuex. The `value` prop and `emit` event are very useful when using a state management tool, like Vuex. You
You can bind the selected value with `:value="$store.myValue"`, and use the `input` event to can bind the selected value with `:value="$store.myValue"`, and use the `input` event to trigger a
trigger a mutation, or dispatch an action or anything else you might need to do when the selection mutation, or dispatch an action or anything else you might need to do when the selection changes.
changes.
```html ```html
<v-select :value="$store.myValue" @input="setSelected" /> <v-select :value="$store.myValue" @input="setSelected" />
``` ```
```js ```js
methods: { methods: {
setSelected(value) { setSelected(value)
// trigger a mutation, or dispatch an action {
} // trigger a mutation, or dispatch an action
}
} }
``` ```
## Single/Multiple
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']" />
## Transforming Selections ## Transforming Selections
When the `options` array contains objects, vue-select returns the whole object as dropdown value 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 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 flexibility. However, there will be situations where you just need to return a single key from an
from an object. object.
### Returning a single key with `reduce` ### Returning a single key with `reduce`
If you need to return a single key, or transform the selection before it is synced, vue-select 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 provides a `reduce` callback that allows you to transform a selected option before it is passed to
the `@input` event. Consider this data structure: the `@input` event. Consider this data structure:
```js ```js
let options = [{code: 'CA', country: 'Canada'}]; 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` 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. prop to receive only the data that's required.
```html ```html
<v-select :options="options" :reduce="country => country.code" label="country" />
<v-select :options="options" :reduce="country => country.code" label="country" />
``` ```
### Deep Nested Values ### Deep Nested Values
The `reduce` property also works well when you have a deeply nested value: The `reduce` property also works well when you have a deeply nested value:
``` ```
{ {
country: 'canada', country: 'canada',
@@ -95,30 +113,42 @@ The `reduce` property also works well when you have a deeply nested value:
} }
} }
``` ```
```html ```html
<v-select :options="options" :reduce="country => country.meta.code" label="country" />
<v-select :options="options" :reduce="country => country.meta.code" label="country" />
``` ```
<reducer-nested-value /> <reducer-nested-value />
## Single/Multiple Selection ## Caveats with `reduce`
By default, vue-select supports choosing a single value. If you need multiple values, use the The most common issue with `reduce` is when the component displays your _reduced_ _value_ instead of
`multiple` boolean prop, much the same way you would on an HTML `<select>` element. When `multiple` it's _label_. This happens when you supply Vue Select a `value` or `v-model` binding with a reduced_
is true, `v-model` and `value` must be an array. value, but the complete option object is not present in the `options` array.
```html <ReducedWithNoMatchingOption />
<v-select multiple v-model="selected" :options="['Canada','United States']" />
``` <<< @/.vuepress/components/ReducedWithNoMatchingOption.vue
<v-select multiple :options="['Canada','United States']" />
In the example above, the component was supplied with an ID that doesn't exist in the `options`
array. When `value` changes, Vue Select searches the supplied options, running each one
through `reduce` until the corresponding option is found. When that option doesn't exist, Vue Select
will end up displaying the `value` supplied.
::: warning
When providing Vue Select with a _reduced_ `value` - the object that the value was reduced from must
exist in the `options` array.
:::
## Tagging ## Tagging
To allow input that's not present within the options, set the `taggable` prop to true. To allow input that's not present within the options, set the `taggable` prop to true.
```html ```html
<v-select taggable multiple /> <v-select taggable multiple />
``` ```
@@ -127,6 +157,7 @@ To allow input that's not present within the options, set the `taggable` prop to
If you want added tags to be pushed to the options array, set `push-tags` to true. If you want added tags to be pushed to the options array, set `push-tags` to true.
```html ```html
<v-select taggable multiple push-tags /> <v-select taggable multiple push-tags />
``` ```
@@ -136,10 +167,11 @@ If you want added tags to be pushed to the options array, set `push-tags` to tru
When combining `taggable` with `reduce`, you must define the `createOption` prop. The 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 `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 will create for you when adding a tag. It should return a value that has the same properties as the
rest of your `options`. rest of your `options`.
If you don't define `createOption`, Vue Select will construct a simple object following this structure: 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 `{[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. like, which is why you'll need to set the function yourself.
@@ -147,28 +179,29 @@ like, which is why you'll need to set the function yourself.
We have a taggable select for adding books to a collection. We're just concerned about getting the 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 book title added, and our server side code will add the author details in a background process. The
user has already selected a book. user has already selected a book.
```js ```js
const options = [ const options = [
{ {
title: "HTML5", title: "HTML5",
author: { author: {
firstName: "Remy", firstName: "Remy",
lastName: "Sharp" lastName: "Sharp"
}
} }
}
]; ];
``` ```
```html ```html
<v-select <v-select
taggable taggable
multiple multiple
label="title" label="title"
:options="options" :options="options"
:create-option="book => ({ title: book, author: { firstName: '', lastName: '' } })" :create-option="book => ({ title: book, author: { firstName: '', lastName: '' } })"
:reduce="book => `${book.author.firstName} ${book.author.lastName}`" :reduce="book => `${book.author.firstName} ${book.author.lastName}`"
/> />
``` ```