💨
【Vue3】multiple属性の複数選択プルダウンで選択した値をemitする
はじめに
vuetify公式を参考に、v-select
で複数選択できるプルダウンを作っていたところ、値を親にemitできず少し沼りました。
template
<template>
<v-container fluid>
<v-select
v-model="selectedFruits"
:items="fruits"
label="Favorite Fruits"
multiple
>
<template v-slot:prepend-item>
<v-list-item
title="Select All"
@click="toggle"
>
<template v-slot:prepend>
<v-checkbox-btn
:color="likesSomeFruit ? 'indigo-darken-4' : undefined"
:indeterminate="likesSomeFruit && !likesAllFruit"
:model-value="likesSomeFruit"
></v-checkbox-btn>
</template>
</v-list-item>
</template>
</v-select>
</v-container>
</template>
script
<script>
export default {
data: () => ({
fruits: [
'Apples',
'Apricots',
'Avocado',
'Bananas',...略
],
selectedFruits: [],
}),
computed: {
likesAllFruit () {
return this.selectedFruits.length === this.fruits.length
},
likesSomeFruit () {
return this.selectedFruits.length > 0
},
},
methods: {
toggle () {
if (this.likesAllFruit) {
this.selectedFruits = []
} else {
this.selectedFruits = this.fruits.slice()
}
},
},
}
</script>
selectの値を受け取る
基本的にinput系の値を取得するときは、v-model
を使用しますが、今回はv-bind
と@input
で入力された値を親コンポーネントに伝える方法をとります。
一択選択の場合
<select>
の@input="$emit('newInput', $event.target.value)"
で、
親コンポーネントはnewInput
を用いてセレクトボックスの値を受け取ることができます。
<template>
<select @input="$emit('newInput', $event.target.value)">
<option v-for="val in selectBox"
:value="val.value"
:selected="inputValue === val.value">
{{val.text}}
</option>
</select>
</template>
<script>
export default{
name:'childSelect',
//親から初期値valueを受け取るprops
props:['inputed'],
data(){
return{
selector:[
{text:'選択肢1',value:'1'},
{text:'選択肢2',value:'2'},
{text:'選択肢3',value:'3'}
],
}
},
}
</script>
複数選択の場合
今回はmultiple
属性のついたプルダウンの値をemitしたので、
$event.target.value
ではなく、$event.target.options
を使用します。
template
<v-container fluid>
<v-select
v-model="selectedFruits"
:items="fruits"
label="Favorite Fruits"
multiple
@input="returnValue($event)" // add
>
<template v-slot:prepend-item>
<v-list-item
title="Select All"
@click="toggle"
>
<template v-slot:prepend>
<v-checkbox-btn
:color="likesSomeFruit ? 'indigo-darken-4' : undefined"
:indeterminate="likesSomeFruit && !likesAllFruit"
:model-value="likesSomeFruit"
></v-checkbox-btn>
</template>
</v-list-item>
</template>
</v-select>
</v-container>
script
<script>
export default {
props: ['inputed'],
data() {
return {
fruits: [
'Apples',
'Apricots',
'Avocado',
'Bananas',...略
],
selectedFruits: [],
}
},
computed: {
likesAllFruit () {
return this.selectedFruits.length === this.fruits.length
},
likesSomeFruit () {
return this.selectedFruits.length > 0
},
},
methods: {
toggle () {
if (this.likesAllFruit) {
this.selectedFruits = []
} else {
this.selectedFruits = this.fruits.slice()
}
},
returnValue($event){
let opt = Object.values($event.target.options).filter(ele=>{
return ele.selected;
})
let values = opt.map(ele=>ele.value);
this.$emit('newInput', values);
}
},
}
</script>
$event.target.options
には``<option>タグに関する情報が入っており、
selectedと
valueも含まれています。 HTMLCollectionの配列なので、
Object.valuesでvalueの配列にしてから
filter()```しました。
最後に、selected
がtrue
の要素のみ取得して新しい配列を作り、その配列に対してmap()
をかけ、value
を抽出したもの新しい配列として返します。
それを親コンポーネントに渡すと、選択したものを配列として渡すことが可能になります。
Discussion