概要
例えばあるカテゴリを選択すると、自動的にそのサブカテゴリが選択できるようにしたい。
Vuetifyのv-select
を2つ使ってその方法を示す。
App.vue
<template> <v-app> <v-select v-on:click="initializeSubcategories" v-model="categories" label="SELECT CATEGORY" item-text="name" :items="categoryList" return-object ></v-select> <v-select v-model="subcategories" label="SELECT SUBCATEGORY" :items="categories.children" item-text="name" ></v-select> <p>categories: {{ categories.children }}</p> <p>subcategories: {{ subcategories }}</p> </v-app> </template> <script> export default { data() { return { categories: '', subcategories: '', categoryList: [ { name: 'CATEGORY 1', code: 'cat 1', children: [ { name: 'SUBCATEGORY 1-1', code: 'subcat 1-1', }, { name: 'SUBCATEGORY 1-2', code: 'subcat 1-2', }, { name: 'SUBCATEGORY 1-3', code: 'subcat 1-3', }, ] }, { name: 'CATEGORY 2', code: 'cat 2', children: [ { name: 'SUBCATEGORY 2-1', code: 'subcat 2-1', }, { name: 'SUBCATEGORY 2-2', code: 'subcat 2-2', }, { name: 'SUBCATEGORY 2-3', code: 'subcat 2-3', }, { name: 'SUBCATEGORY 2-4', code: 'subcat 2-4', }, ] }, { name: 'CATEGORY 3', code: 'cat 3', children: [ { name: 'SUBCATEGORY 3-1', code: 'subcat 3-1', }, ] }, ], } }, methods: { initializeSubcategories() { this.subcategories = ''; }, }, }; </script>
実行結果
- Click the Category Select
- Select a Category
- Click the Subcategory Select
- Select a Subcategory
- Bug: if no categories are selected, then a subcategory is no data available
解説
カテゴリデータを次のようにします。
<script> export default { data() { return { categories: '', subcategories: '', categoryList: [ { name: 'CATEGORY 1', code: 'cat 1', children: [ { name: 'SUBCATEGORY 1-1', code: 'subcat 1-1', }, { name: 'SUBCATEGORY 1-2', code: 'subcat 1-2', }, { name: 'SUBCATEGORY 1-3', code: 'subcat 1-3', }, ] }, { name: 'CATEGORY 2', code: 'cat 2', children: [ { name: 'SUBCATEGORY 2-1', code: 'subcat 2-1', }, { name: 'SUBCATEGORY 2-2', code: 'subcat 2-2', }, { name: 'SUBCATEGORY 2-3', code: 'subcat 2-3', }, { name: 'SUBCATEGORY 2-4', code: 'subcat 2-4', }, ] }, { name: 'CATEGORY 3', code: 'cat 3', children: [ { name: 'SUBCATEGORY 3-1', code: 'subcat 3-1', }, ] }, ], } }, }; </script>
基本文法
v-select
の基本は次のとおりです。
<v-select label="SELECT CATEGORY" :items="categoryList" ></v-select>
label
は選択肢の名称を記入できます。これはオプションです。
ただし、このままだと[object, object]
と表示されます。
実行結果
解決策
これを解決する方法は2つあります。
その1
一つ目はカテゴリデータのキーname
をtext
に変えることです。つまり、次のようにします。
<script> export default { data() { return { categoryList: [ { text: 'CATEGORY 1', code: 'cat 1', children: [ { ....... }, { text: 'CATEGORY 3', code: 'cat 3', children: [ ........ ] }, ], } }, }; </script>
というのも、:items
はデフォルトでは"categoryList"
で指定したキーtext
を参照するからです。
その2
しかし、前者の方法はとても不便です。もう一つはカテゴリデータは変更せずに、item-text
を追加する方法です。このオプションでデフォルトの参照キーをname
に変更します。
<v-select label="SELECT CATEGORY" item-text="name" :items="categoryList" ></v-select>
実行結果
セレクトの戻り値を取得する方法
次にv-select
で選択した戻り値を取得する方法を示します。
まず、戻り値を入れる変数を次のように設定します。
<v-select v-model="categories" label="SELECT CATEGORY" item-text="name" :items="categoryList" ></v-select> <p>categories: {{ categories }}</p> .... data() { return { categories: '', categoryList: [ ...... ] ....
v-select
のオプションにv-model
を追加して、data()
にcategories: '',
を追加します。
しかし、これだけでは戻り値を取得できません。
先ほどと同じように、:items
はデフォルトでは"categoryList"
で指定したキーvalue
(もし存在すれば)を戻り値として参照します。ですので、キーをcode
からvalue
に変更すれば、戻り値を取得できます。しかし、それよりもv-select
のオプションにitem-value
を追加して、戻り値の参照キーを変更したほうが簡単です。参照キーは配列でも問題ありませんので、item-value="children"
としても構いません。
<v-select v-model="categories" label="SELECT CATEGORY" item-text="name" item-value="children" :items="categoryList" ></v-select> <p>categories: {{ categories }}</p>
実行結果
サブカテゴリについて
サブカテゴリについてもカテゴリと同じように実行できます。
data()
に変数subcategories
を追加する。v-select
のオプションにitem-text="name"
を追加する。v-select
のオプションにitem-value="code"
を追加する。v-select
に:items="categories"
を追加する。
このように修正すれば、カテゴリの選択肢からサブカテゴリの選択肢が絞られるような実装となります。
バグの修正について
カテゴリが選択されたら、それに従ってサブカテゴリも選択されるようなプログラムはこれでできます。
しかし、このままではいくつかのバグが生じてしまいます。
- CATEGORY 1およびSUBCATEGORY 1-1を選んだ後に、「やっぱ、カテゴリを変更する」と思って、カテゴリをCATEGORY 2変更するとカテゴリとサブカテゴリが不一致になってしまう(カテゴリはCATEGORY 2であり、サブカテゴリはSUBCATEGORY 1-1となる)。
- カテゴリを選ばずに、いきなりサブカテゴリを選択すると「No data available」と表示されてしまう。
一つ目のバグはsubcategories
を初期化する(空文字にする)関数を作成して、カテゴリがクリックされるとそれが実行されるように修正すれば直ります。
<template> <v-app> <v-select v-on:click="initializeSubcategories" v-model="categories" label="SELECT CATEGORY" item-text="name" :items="categoryList" return-object ></v-select> ..... ..... name: 'SUBCATEGORY 3-1', code: 'subcat 3-1', }, ..... }, methods: { initializeSubcategories() { this.subcategories = ''; }, }, }; </script>
もう一つのバグはcategories
が空文字ならば二つ目のセレクトがクリックできないように修正すれば直ると思います(未実装)。
僕から以上