状況
Vue.jsでテーブルを作成し、テーブルのデータごとに動的にモーダルを表示させようとするも、何かおかしい。
前提
$ vue --version
@vue/cli 4.5.11
なお、本記事では Vue Materialのテーブルコンポーネント を使用しています。
百聞は一見にしかずということで
状況をアニメーションで貼っておきます。
見ての通り、どのモーダルボタンをクリックしても3番目の要素しか表示されない。
しかも背景がかなり暗い。
出来れば親でモーダルを発火させるボタンを押せて、モーダルの状態を親で管理できるようにしたい。
該当コード
Parent.vue
<template>
<div>
<md-table v-model="products">
<md-table-row slot="md-table-row" slot-scope="{ item }">
<md-table-cell md-label="ID">{{ item.id }}</md-table-cell>
<md-table-cell md-label="ユーザー名">{{ item.user }}</md-table-cell>
<md-table-cell md-label="アクション">
<button @click="modalState = true">モーダル表示</button>
<md-dialog :md-active.sync="modalState">
<Child :user="item.user" :item-id="item.id" />
</md-dialog>
</md-table-cell>
</md-table-row>
</md-table>
</div>
</template>
<script lang="ts">
import Child from './Child.vue'
import Vue from 'vue'
export default Vue.extend({
name: 'TableContent',
components: {
Child,
},
data() {
return {
products: [
{ id: 1, user: '伊藤' },
{ id: 2, user: '田中' },
{ id: 3, user: '佐久間' },
],
modalState: false,
}
},
})
</script>
Child.vue
<template>
<div style="text-align: center">{{ itemId }} : {{ user }}</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'Vue:Child',
props: {
itemId: {
type: Number,
required: true,
},
user: {
type: String,
default: '',
},
},
})
</script>
問題の原因
初歩的なミスをしていました。
**modalState
**にテーブルごとのユニークな値を与えていなかった為、ボタンを押すと全てのモーダルがtrueとなり、全て重なって表示されており、背景も暗くなっているということでした。
コード修正
Parent.vue
<template>
<div>
<md-table v-model="products">
<md-table-row slot="md-table-row" slot-scope="{ item }">
<md-table-cell md-label="ID">{{ item.id }}</md-table-cell>
<md-table-cell md-label="ユーザー名">{{ item.user }}</md-table-cell>
<md-table-cell md-label="アクション">
<button @click="$set(modalState, item.id, true)">モーダル表示</button> <!-- テーブルごとのmodalStateを制御 -->
<md-dialog :md-active.sync="modalState[item.id]"> <!-- ユニークな値を追加 -->
<Child :user="item.user" :item-id="item.id" />
</md-dialog>
</md-table-cell>
</md-table-row>
</md-table>
</div>
</template>
<script lang="ts">
import Child from './Child.vue'
import Vue from 'vue'
export default Vue.extend({
name: 'TableContent',
components: {
Child,
},
data() {
return {
products: [
{ id: 1, user: '伊藤' },
{ id: 2, user: '田中' },
{ id: 3, user: '佐久間' },
],
modalState: {}, // 定義をオブジェクト形式に変更
}
},
})
</script>
無事動的にモーダルを表示することができました!
参考
https://stackoverflow.com/questions/49580396/vuetify-how-to-open-and-close-dialogs-within-a-data-table
https://vuematerial.io/components/table