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の中にボタンもダイアログも含めるのが公式の使い方であることを学びました。

コメント