LoginSignup
2
1

More than 3 years have passed since last update.

Vue.jsのテーブルで動的にモーダルを表示させる

Posted at

状況

Vue.jsでテーブルを作成し、テーブルのデータごとに動的にモーダルを表示させようとするも、何かおかしい。

前提

$ vue --version
@vue/cli 4.5.11

なお、本記事では Vue Materialのテーブルコンポーネント を使用しています。

百聞は一見にしかずということで

状況をアニメーションで貼っておきます。

sample.gif

見ての通り、どのモーダルボタンをクリックしても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>

sample2.gif

無事動的にモーダルを表示することができました!

参考

https://stackoverflow.com/questions/49580396/vuetify-how-to-open-and-close-dialogs-within-a-data-table
https://vuematerial.io/components/table

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1