【Vue.js】v-dialogの表示にはv-modelを使う

Vuetifyのv-dialogを使ってダイアログのコンポーネントを作成してましたが、なぜかダイアログが表示できずハマったため、備忘録としてまとめます。

  • Vue.js 3.3.4
  • Vuetify 3.4.4
目次

問題

以下のコードのように、v-ifディレクティブを用いてv-dialogの表示・非表示を制御しようとしていました。

<script setup lang="ts">
import { ref } from 'vue';

const isActive = ref(false);

const openDialog = (): void => {
  isActive.value = true;
};

const closeDialog = (): void => {
  isActive.value = false;
};
</script>

<template>
  <v-app>
    <v-container>
      <v-btn @click="openDialog">ダイアログを開く</v-btn>
      
      <!-- v-if で表示・非表示を切り替えたいが上手くいかない -->
      <v-dialog v-if="isActive">
        <v-card>
          <v-card-title>ダイアログ</v-card-title>
          <v-card-text>
            <p>
              Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo distinctio non quo officiis praesentium
              provident, iste deleniti culpa mollitia ab modi eum qui animi ipsum. Voluptates mollitia fugiat sed eius?
            </p>
          </v-card-text>
          <v-card-actions>
            <v-spacer></v-spacer>
            <v-btn @click="closeDialog">閉じる</v-btn>
          </v-card-actions>
        </v-card>
      </v-dialog>
    </v-container>
  </v-app>
</template>

「ダイアログを開く」ボタンを押すとVue DevTools上では確かにVDialogコンポーネントが存在しているのですが、なぜかサイズが「0 × 0」となってしまい、ダイアログが表示されない状況でした。

解決方法

v-ifではなくv-modelを使うことでダイアログが狙い通りに表示されるようになりました。

<script setup lang="ts">
import { ref } from 'vue';

const isActive = ref(false);

const openDialog = (): void => {
  isActive.value = true;
};

const closeDialog = (): void => {
  isActive.value = false;
};
</script>

<template>
  <v-app>
    <v-container>
      <v-btn @click="openDialog">ダイアログを開く</v-btn>

      <!-- v-if から v-model に変更 -->
      <v-dialog v-model="isActive" width="500">
        <v-card>
          <v-card-title>ダイアログ</v-card-title>
          <v-card-text>
            <p>
              Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo distinctio non quo officiis praesentium
              provident, iste deleniti culpa mollitia ab modi eum qui animi ipsum. Voluptates mollitia fugiat sed eius?
            </p>
          </v-card-text>
          <v-card-actions>
            <v-spacer></v-spacer>
            <v-btn @click="closeDialog">閉じる</v-btn>
          </v-card-actions>
        </v-card>
      </v-dialog>
    </v-container>
  </v-app>
</template>

すると綺麗に表示されました!

公式ドキュメントからの補足

Vuetifyの公式ドキュメントを見たところ、以下のコードのようにv-dialogコンポーネントの中に、ボタンもダイアログも含めるのが正しい使い方のようです。

<!-- <script> は不要 -->
<template>
  <v-app>
    <v-container>
      <v-dialog width="500">
        <!-- v-btn コンポーネントも v-dialog に含む -->
        <template v-slot:activator="{ props }">
          <v-btn v-bind="props" text="ダイアログを開く"> </v-btn>
        </template>

        <!-- isActive はVuetify側が用意している変数 -->
        <template v-slot:default="{ isActive }">
          <v-card title="ダイアログ">
            <v-card-text>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
              dolore magna aliqua.
            </v-card-text>

            <v-card-actions>
              <v-spacer></v-spacer>

              <v-btn text="閉じる" @click="isActive.value = false"></v-btn>
            </v-card-actions>
          </v-card>
        </template>
      </v-dialog>
    </v-container>
  </v-app>
</template>

まとめ

Vuetifyのv-dialogコンポーネントを使う際はv-ifではなくv-modelで表示・非表示を切り替えること、そもそもv-dialogの中にボタンもダイアログも含めるのが公式の使い方であることを学びました。

参考文献

技術書が好きなエンジニア向け

あわせて読みたい
「技術書の内容が頭に入らない」を防ぐ5つの読書方法 「技術書の内容が頭に入らない」を防ぐための5つの読書方法を紹介します。最後まで読めば効率よくインプットできるようになります。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

未経験でSESから従業員300名以上の自社開発企業に転職しました。業務や個人開発で直面した問題や、転職・学習の経験を発信していきます。

コメント

コメントする

目次