目的
本記事の目的は、Vuetifyの<v-data-table>
を使用して、複数条件で絞り込み、動的にテーブルの表示を切り替えることである。
やったこと
はじめにVuetifyのV-Data-TableのAPI を読んで、custom-filter
プロパティを使用しようと考えた。
しかし、custom-filter
プロパティの引数であるsearch
は一つしか変数を持つことができない。
そこで、V-Data-TableのAPIのheadersに記述されているfilter
プロパティを使用することで複数項目のフィルタリングを可能にした。
作成画面
使用環境
- Vue.js: "^2.6.11",
- Vue-Router: "^3.2.0",
- Vuetify: "^2.3.21"
ファイルの説明
- sampleDataTable.json : テーブルに格納するサンプルデータ
- Table.vue : テーブルを表示させる為のVueファイル
ソースコード
{
"data": [
{
"name": "Frozen Yogurt",
"calories": 159,
"fat": 6.0,
"carbs": 24,
"protein": 4.0,
"iron": "1%"
},
{
"name": "Ice cream sandwich",
"calories": 237,
"fat": 9.0,
"carbs": 37,
"protein": 4.3,
"iron": "1%"
},
{
"name": "Eclair",
"calories": 262,
"fat": 16.0,
"carbs": 23,
"protein": 6.0,
"iron": "7%"
},
{
"name": "Cupcake",
"calories": 305,
"fat": 3.7,
"carbs": 67,
"protein": 4.3,
"iron": "8%"
},
{
"name": "Gingerbread",
"calories": 356,
"fat": 16.0,
"carbs": 49,
"protein": 3.9,
"iron": "16%"
},
{
"name": "Jelly bean",
"calories": 375,
"fat": 0.0,
"carbs": 94,
"protein": 0.0,
"iron": "0%"
},
{
"name": "Lollipop",
"calories": 392,
"fat": 0.2,
"carbs": 98,
"protein": 0,
"iron": "2%"
},
{
"name": "Honeycomb",
"calories": 408,
"fat": 3.2,
"carbs": 87,
"protein": 6.5,
"iron": "45%"
},
{
"name": "Donut",
"calories": 452,
"fat": 25.0,
"carbs": 51,
"protein": 4.9,
"iron": "22%"
},
{
"name": "KitKat",
"calories": 518,
"fat": 26.0,
"carbs": 65,
"protein": 7,
"iron": "6%"
}
]
}
<template>
<v-data-table :headers="headers" :items="desserts" item-key="name" class="elevation-1 pa-6">
<template v-slot:top>
<v-container fluid>
<v-row>
<v-col cols="4">
<v-row class="pa-6">
<!-- Filter for Desert -->
<v-text-field
v-model="dessertFilterValue"
type="text"
label="Desert Name">
</v-text-field>
</v-row>
</v-col>
<v-col cols="4">
<v-row class="pa-6">
<!-- Filter for Calories -->
<v-select
:items="caloriesList"
v-model="caloriesFilterValue"
label="Calories"
></v-select>
</v-row>
</v-col>
<v-col cols="4">
<v-row class="pa-6">
<!-- Filter for Fat-->
<v-text-field
v-model="FatFilterValue"
type="text"
label="Fat">
</v-text-field>
</v-row>
</v-col>
</v-row>
</v-container>
</template>
</v-data-table>
</template>
<script>
// Table info.
import tableData from './sampleDataTable';
export default {
name: 'Table',
data() {
return {
// We need some values for our select.
caloriesList: [
{text: "All", value: null},
{text: "Only 237", value: 237},
{text: "Only 305", value: 305},
],
// Filter models.
dessertFilterValue: '',
FatFilterValue: '',
caloriesFilterValue: null,
// Table data.
desserts: tableData.data,
}
},
computed: {
headers() {
return [
{
text: 'Dessert (100g serving)',
align: 'left',
sortable: false,
value: 'name',
filter: this.nameFilter,
},
{
text: 'Calories',
value: 'calories',
filter: this.caloriesFilter,
},
{
text: 'Fat (g)',
value: 'fat',
filter: this.FatFilter,
},
{text: 'Carbs (g)', value: 'carbs'},
{text: 'Protein (g)', value: 'protein'},
{text: 'Iron (%)', value: 'iron'},
]
},
},
methods: {
nameFilter(value) {
// this.dessertFilterValue がなければフィルタリングしない
if (!this.dessertFilterValue) {
return true
}
return value.toLowerCase().includes(this.dessertFilterValue.toLowerCase());
},
caloriesFilter(value) {
if (!this.caloriesFilterValue) {
return true
}
return value === this.caloriesFilterValue
},
FatFilter(value) {
if(!this.FatFilterValue) {
return true
}
return value === parseInt(this.FatFilterValue)
}
}
}
</script>
上記のコードは、
Vuetifyの<v-text-field>
を使用して、
<v-text-field
v-model="dessertFilterValue"
type="text"
label="Desert Name">
</v-text-field>
のようにv-modelを定義する。
また下記のように、Vue.jsのdata
プロパティにv-modelの初期値を定義する。
dessertFilterValue: '',
FatFilterValue: '',
caloriesFilterValue: null,
そして、computed() の headers() の各テーブルの項目内でfilter
プロパティを定義する。
computed: {
headers() {
return [
{
text: 'Dessert (100g serving)',
align: 'left',
sortable: false,
value: 'name',
filter: this.nameFilter,
},
{
text: 'Calories',
value: 'calories',
filter: this.caloriesFilter,
},
{
text: 'Fat (g)',
value: 'fat',
filter: this.FatFilter,
},
{text: 'Carbs (g)', value: 'carbs'},
{text: 'Protein (g)', value: 'protein'},
{text: 'Iron (%)', value: 'iron'},
]
},
},
最後に、methodsの各関数でフィルタリングすることでテーブルの表示を切り替えることができる。
例えばDesert Name
でフィルタリングをかけたい場合、
nameFilter(value) {
// this.dessertFilterValue がなければフィルタリングしない
if (!this.dessertFilterValue) {
return true
}
return value.toLowerCase().includes(this.dessertFilterValue.toLowerCase());
},
とすることで、v-modelが変化するたびに動的にテーブルの表示を切り替えることが可能になる。
結論
簡潔かつシンプルにフィルタリングできるVuetifyは凄い!!!