Vueで<details>と<dialog>を扱う方法

2024/12/23に公開

これは LAPRAS Advent Calendar 2024の23日目の記事です。
https://qiita.com/advent-calendar/2024/lapras

概要

2024年12月現在、<details>要素と<dialog>要素をv-modelで制御することはできません
このPRがリリースされればできるようになります)

現時点では、それらの要素をVueで扱うにはやや特殊な方法が必要です。
本記事ではその方法を解説します。

<details>要素

実装

コード

<details
  :open="isDetailsOpen"
  @toggle="isDetailsOpen = $event.target.open"
>
  <summary>ここを押すと開閉します</summary>
  <p>これが中身です</p>
</details>

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

const isDetailsOpen = ref(false);
</script>

解説

  • <details>の開閉状態を表すref変数をopen属性にバインドしています
  • 開閉時に発火されるtoggleイベントを購読し、$event.target.openで開閉状態を更新しています

<dialog>要素

実装

コード

<template>
  <dialog ref="dialog" @close="onClose">
    <form method="dialog">
      <p>どっちが好き?</p>

      <button type="submit" value="きのこ🍄">きのこ</button>
      <button type="submit" value="たけのこ🎋">たけのこ</button>
    </form>
  </dialog>

  <button @click="showModal">モーダルを開く</button>
  <p v-if="result">私が好きなのは「{{ result }}」です。</p>
</template>

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

const result = ref("");
const dialog = ref<HTMLDialogElement | null>(null);

const showModal = () => {
  dialog.value?.showModal();
};
const onClose = () => {
  // ボタン押下時にvalueがreturnValueに入る
  const returnValue = dialog.value?.returnValue;
  result.value = returnValue ?? "";
};
</script>

解説

  • <dialog>要素にref属性を付与し、要素自体のshowModal()メソッドを呼び出すことでダイアログを開いています(※)。
  • ダイアログを閉じるメソッドは必要ありません。<form method="dialog">の場合、submitされると自動で閉じるようになっているためです。
  • ダイアログが閉じられたとき、<dialog>要素のreturnValueには押されたsubmitボタンのvalueが自動で入ります。

<dialog>要素にもopen属性はあるのですが、この属性を直接操作するのは非推奨であるため、refを通して操作しています。

最後に

こちらからは以上です。よいお年を🎍

Discussion