Chapter 36無料公開

ダイアログ (Dialog): v-dialog

超Lチカ団編集局
超Lチカ団編集局
2024.01.19に更新

ダイアログ (Dialog): v-dialog

ボタンなどを押すと、画面内にポップアップするウィンドウを出すことができるコンポーネントです。

基本

ダイアログは、構成要素としてダイアログを表示するためにトリガーになる要素(ボタン v-btn など)と、ダイアログの実態になる要素(v-sheetv-card など)を必要とします。

sample.gif

<template>
  <v-container >
    <v-btn
      color="primary"
    >
      Open Dialog
      <v-dialog
        v-model="dialog"
        activator="parent"
      >
        <v-sheet>
          <v-sheet class="my-2 mx-5">
            <h2>Dialog</h2>

            <p class="my-4">
              Please confirm information!
            </p>

            <v-btn color="primary" block @click="dialog = false">Close</v-btn>
          </v-sheet>
        </v-sheet>
      </v-dialog>
    </v-btn>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      dialog: false,
    }
  },
}
</script>

ダイアログの要素は実態をもっておらず、ボタンと表示される実態(上の例では v-card)を結合して、ダイアログとして機能させる役割をします。

トリガーとなるボタンを親要素とし、その子要素として v-doalog を設置し、さらにその子要素として、ダイアログの実体になる v-card を配置します。

ダイアログは、v-model に指定された変数が true のときに開き、false のときに閉じます。上の例では v-btn を押すと閉じます。

なお、デフォルトではダイアログの外側をクリックしてもダイアログは閉じます。ダイアログの外をクリックしたときに閉じないようにするには、persistent prop を使います。これを使うと、ボタンを押したときしかダイアログは閉じなくなります。

sample.gif

<template>
  <v-container >
    <v-btn
      color="primary"
    >
      Open Dialog
      <v-dialog
        v-model="dialog"
        persistent
        activator="parent"
      >
        <v-sheet>
          <v-sheet class="my-2 mx-5">
            <h2>Dialog</h2>

            <p class="my-4">
              Please confirm information!
            </p>

            <v-btn color="primary" block @click="dialog = false">Close</v-btn>
          </v-sheet>
        </v-sheet>
      </v-dialog>
    </v-btn>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      dialog: false,
    }
  },
}
</script>

v-slot:activator を使う方法

ダイアログの構成方法は v-menu  とよく似ています。v-menu と同様に、v-slot:activator を使って下記のように書くこともできます。

動作や見かけは、前述の例とまったく同じになります。

sample.gif

<template>
  <v-container >
      <v-dialog
        v-model="dialog"
        activator="parent"
      >
      <template v-slot:activator="{ props }">
        <v-btn color="primary" v-bind="props"> Open Dialog</v-btn>
      </template>
      
      <v-sheet>
        <v-sheet class="my-2 mx-5">
          <h2>Dialog</h2>

          <p class="my-4">
            Please confirm information!
          </p>

          <v-btn color="primary" block @click="dialog = false">Close</v-btn>
        </v-sheet>
      </v-sheet>
    </v-dialog>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      dialog: false,
    }
  },
}
</script>

この方法でダイアログを作る場合、デフォルトスロット v-slot="{ isActivate }" を使うとダイアログをアクティベート(表示状態に)するたの変数を <script> セクションで定義しなくてすみます。

<template>
  <v-container >
      <v-dialog>
      <template v-slot:activator="{ props }">
        <v-btn color="primary" v-bind="props"> Open Dialog</v-btn>
      </template>
      <template v-slot="{ isActivate }">
        <v-sheet>
          <v-sheet class="my-2 mx-5">
            <h2>Dialog</h2>

            <p class="my-4">
              Please confirm information!
            </p>

            <v-btn color="primary" block @click="isActivate.value = false">Close</v-btn>
          </v-sheet>
        </v-sheet>
      </template>
    </v-dialog>
  </v-container>
</template>

ダイアログの操作として「閉じる」以外の操作がないような、シンプルなダイアログの場合にはこの方法が便利です。

v-model でダイアログを強制的に開く方法

v-btn (トリガー) と v-dialog の間に親子関係がなく、なおかつ v-slot 使わなくても、v-btn を押したときに v-dialogv-model に設定した変数を true にする処理を書けば、ダイアログは開きます。

ただし v-slot:activator を使う時とはダイアログの開き方が変わります。

sample.gif

<template>
  <v-container >
    <v-btn color="primary" @click="dialog = true"> Open Dialog</v-btn>

    <v-dialog
      v-model="dialog"
    >
      <v-sheet>
        <v-sheet class="my-2 mx-5">
          <h2>Dialog</h2>

          <p class="my-4">
            Please confirm information!
          </p>

          <v-btn color="primary" block @click="dialog = false">Close</v-btn>
        </v-sheet>
      </v-sheet>
    </v-dialog>
    
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      dialog: false,
    }
  },
}
</script>

このように、v-slot:activatoractivator="parent" で指定されていないボタンを使ってダイアログを開くと、ダイアログがボタンの位置から開くアニメーションになりません。

ダイアログが開くときに、押したボタンからダイアログがポップアップしてくるアニメーションを使うときは、前述のように v-slot:activatoractivator="parent" を使う必要があります。

ポップアップ時のアニメーションを設定する

transition prop を使うと、ダイアログのポップアップ時のアニメーションを指定できます。デフォルトは dialog-transition です。

sample.gif

<template>
  <v-container >
    <v-btn color="primary" @click="dialog = true"> Open Dialog</v-btn>

    <v-dialog
      v-model="dialog"
      transition="dialog-top-transition"
    >
      <v-sheet>
        <v-sheet class="my-2 mx-5">
          <h2>Dialog</h2>

          <p class="my-4">
            Please confirm information!
          </p>

          <v-btn color="primary" block @click="dialog = false">Close</v-btn>
        </v-sheet>
      </v-sheet>
    </v-dialog>
    
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      dialog: false,
    }
  },
}
</script>

設定可能な transition の一覧は下記にあります。

transition を指定するときは、上記ページにある transition のクラス名の先頭の v- を削除します。たとえば、v-slide-x-transitiontransition="slide-x-transition" のように設定します。

なお、なぜか上記ページのリストには含まれていませんが、下記の transition も使用できます。

  • dialog-top-transition
  • dialog-bottom-transition

ダイアログに複数の機能をもつボタンを設置する

ダイアログに複数のボタンを設置して、押したボタンによって違う挙動をさせることもできます。下の例では、OK ボタンを押すと数字をひとつ増やしてダイアログを閉じ、Cancel を押したときは数字を増やさずダイアログを閉じます。

sample.gif

<template>
  <v-container>
    <v-btn
      @click="dialog = true"
      color="primary"
    >
      Open Dialog
    </v-btn>

    <h2>
      {{counter}}
    </h2>
      
    <v-dialog
      v-model="dialog"
    >
      <v-sheet>
        <v-sheet class="my-2 mx-5">
          <h2>Dialog!</h2>

          <p class="my-4">
            数字を1増やします。数字を1増やします。
          </p>

          <div class="d-flex justify-end my-2">
            <v-btn class="mx-2" color="primary" @click="click(true)">OK</v-btn>
            <v-btn class="mx-2" color="secondary" @click="click(false)">Cancel</v-btn>
          </div>
        </v-sheet>
      </v-sheet>
    </v-dialog>

  </v-container>
</template>
<script>
export default {
  data () {
    return {
      dialog: false,
      counter: 0,
    }
  },
  methods: {
    click(flag){
      if ( flag ){
        this.counter ++;
      }
      this.dialog = false;
    }
  }
}
</script>

ボタンを押さずに、ダイアログの外側をクリックしてダイアログを閉じたときは、単純にダイアログを閉じる以外の処理は行われません(上の例では this.dialog=false とした時と同じ動作になる)。

ダイアログの内部をスクロール可能にする

ダイアログに表示する情報量が多いときに、ダイアログ内をスクロールできるようにしたいことがあります。そのようなときは scrollable prop を使います。

sample.gif

<template>
  <v-container >
    <v-btn
      color="primary"
    >
      Open Dialog
      <v-dialog
        v-model="dialog"
        scrollable
        activator="parent"
      >
        <v-sheet class="my-2 mx-5 pa-3" height="50vh">

          <v-list>
            <v-list-item
              v-for="n in 20"
              :key="n"
              :value="n"
              :title="'Item ' + n"
            ></v-list-item>
          </v-list>            

          <v-btn color="primary" block @click="dialog = false">Close</v-btn>
        </v-sheet>
      </v-dialog>
    </v-btn>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      dialog: false,
    }
  },
}
</script>

入れ子のダイアログ

ダイアログは入れ子にすることもできます。

sample.gif

<template>
  <v-container >
    <v-btn
      color="primary"
    >
      Open Dialog
      <v-dialog
        v-model="dialog1"
        activator="parent"
      >
        <v-sheet class="my-2 mx-5 pa-3">
          <div class="mx-3 my-3">Dialog 1</div> 

          <v-btn color="primary" class="mx-3">Open Dialog
            <v-dialog
              v-model="dialog2"
              activator="parent"
            >
              <v-sheet class="my-2 mx-5 pa-3">
                <div class="mx-3 my-3">Dialog 2</div>

                <v-btn color="secondary" @click="dialog2 = false">Close</v-btn>
              </v-sheet>
            </v-dialog>
          </v-btn>

          <v-btn color="secondary" @click="dialog1 = false">Close</v-btn>
        </v-sheet>
      </v-dialog>
    </v-btn>
  </v-container>
</template>
<script>
export default {
  data () {
    return {
      dialog1: false,
      dialog2: false
    }
  },
}
</script>

上の例では2つのダイアログをネストしていますが、さらに多くのダイアログをネストすることも可能です。

その他

詳しくは、公式ドキュメントを参照してください。