起きたこと
todoアプリの編集機能を作成中、編集機能を押すと追加したtodoアプリ分モーダルが表示されてしまうというバグが発生。
よって、編集ボタンを押すと必ず2つ目のモーダルが表示されてしまっていた。
関連ある技術
- Vue3
- Vuetify3
解決したいこと
1つ1つのtodoのモーダルを表示できるようにしたい
考えるべきこと
今回は、なぜ2重に表示されてしまうのかを考える必要がある。
まず、todo自体の挙動の確認からすると…
- todo追加
- todoが画面に表示される
- todo編集ボタンを押す
- モーダルが表示される
・キャンセルボタンを押して閉じる
・更新ボタンを押して閉じる - モーダルを閉じる
単体のtodoを作成する手順はこんな感じ。
次に、コードの確認。
<template>
<v-dialog
v-model="showDialog"
persistent
width="1024"
>
<template v-slot:activator="{ props }">
<v-btn
class="ma-2"
color="blue"
height="40"
type="submit"
v-bind="props"
>
編集
</v-btn>
</template>
...
</v-dialog>
...
</template>
<script setup>
import { computed, ref } from 'vue';
import { useStore } from 'vuex';
const store = useStore();
const newTodoTheme = ref("");
const todoValues = computed(() => store.getters.todoList);
const showDialog = ref(false);
...
</script>
vuetifyの公式から、ダイアログがあったので、そのコードで必要な部分だけ抽出。
上記コードで、<template v-slot:activator="{ props }">
の部分は編集ボタンを押すとトリガーとなり、モーダル(特定のコンポーネント)が表示(アクティベート)される処理となっている。
showDialogで、refを使用していることからリアクティブにtrue/falseとすることができるが、このままだと単一のtodoしか指定ができない。
ここでのキーポイントは
- showDialogをどう宣言していくかということ
- 各todoのindex番号を用いる
todoを複数追加ということは、オブジェクトでキーを各todoのインデックス、バリューに各todoのインデックスのbooleanを持たせればいいので、下記のような宣言に変更。
const showDialog = ref({});
そして、今回は、親コンポーネントから値を受け取ってきたりすることはないので、template自体の数を少なくし可読性を良くするために、先ほどのコードも修正していくこととする。
編集ボタンを押したときに、clickイベントが発火し、各要素のインデックスを渡しやすいなと考えたので、以下のように変更。
<template>
<v-btn
class="ma-2"
color="blue"
height="40"
type="submit"
@click="handleOpenModal(index)"
>
編集
</v-btn>
...
</template>
<script setup>
...
const showDialog = ref({});
...
const handleOpenModal = (index) => {
showDialog.value[index] = true;
}
引数で、indexを渡すことで、各要素のインデックスの制御もしやすくなった。
ちなみに、showDialog.valueとすることで、vue3の場合は要素にアクセスできる。(vue2からvue3やってる人にとっては、初見殺しだったりする)
上記コードで、わかりづらい人向けにconsole.logで値を出してみると下記のようになります↓↓↓
オブジェクト内で、インデックス毎に管理されているのがこれでわかるかと思います。
そして、再度挙動の確認をしてみると….
でけた!!!!
今回のバグが起きた原因としては、
- todoが複数になったときに対応してなかった
- 各todo毎にモーダルのデータ管理をしてあげなかった
以上が原因だったと思います。
vue3まだまだ理解が足りぬと感じることが多いですが、僕と同じような状況で困っている人がいたら、ぜひこの記事を参考にしてみてください!