vue-material-modal-dialog

A reusable modal dialog for Vue Material.

Purpose

In Vue Material, components showing a dialog have to contain an MdDialog, or a component based on an MdDialog.

There will be a separate dialog instance nested in each such component, even if different components use the same dialog or if components are repeated by v-for.

This repository provides a new component, MdModalDialog, as a substitute for Vue Material's MdDialog. It offers the following features:

  • For each dialog there is only a single instance, no matter how many components use it
  • MdModalDialog supports the same props and events as MdDialog
  • Simple API: showing the dialog returns a promise which will be fulfilled or rejected
    when the dialog is closed
  • Custom properties can be passed to a dialog

Usage

Installation

npm install vue-material-modal-dialog
yarn add vue-material-modal-dialog

Registering MdModalDialog

import MdModalDialog from 'vue-material-modal-dialog'
import 'vue-material-modal-dialog/dist/md-modal-dialog.css'

    ...
// This must come after Vue.use(VueMaterial):
Vue.use(MdModalDialog)

Controlling modal dialogs

MdModalDialog provides these functions:

  • vm.$modal.show(dialog, [props])

    • {Vue component} dialog
    • {Object} [props]

    Shows a dialog component, can pass properties to the dialog instance.

    Returns a Promise that can be fulfilled by vm.$modal.submit() and
    rejected by vm.$modal.cancel(). Both functions close the dialog.

  • vm.$modal.submit([result])

    • {Any} [result]

    Closes the dialog and fulfills the Promise; can return a result.

  • vm.$modal.cancel([reason])

    • {Any} [reason]

    Closes the dialog and rejects the Promise; can return a reason.

Creating modal dialog components

Just use MdModalDialog in the same way as MdDialog (without md-active),
for example for an input dialog:

<template>
  <md-modal-dialog>
    <md-dialog-title>Guess a number</md-dialog-title>

    <md-dialog-content>
      <md-field>
        <label>A number</label>
        <md-input type="number" v-model="number" />
      </md-field>
    </md-dialog-content>

    <md-dialog-actions>
      <md-button @click="$modal.submit(number)">Submit</md-button>
      <md-button @click="$modal.cancel()">Cancel</md-button>  
    </md-dialog-actions>
  </md-modal-dialog>
</template>

<script>
  export default {
    name: 'GuessDialog',
      ...
  }
</script>

Some other component will show GuessDialog and receive the guessed number:

<template>
    ...
  <md-button @click="guess">Guess a number</md-button>
    ...
</template>

<script>
import GuessDialog from '@/components/guess-dialog'

export default {
    ...
  methods: {
    guess() {
      this.$modal
          .show(GuessDialog)
          .then(number => {
            // Do something with the guessed number
          })
          .catch(reason => {
            // Must be specified even if the reason is
            // irrelevant in order to avoid runtime warnings.
          })      
    } 
  },
}
</script>

Passing properties to modal dialogs

Let's extend the example with an upper limit to the guessed number.
Use v-slot to make GuessDialog accept property max:

<template>
  <md-modal-dialog v-slot="{ max }">
    <md-dialog-title>Guess a number up to {{ max }}</md-dialog-title>

    <md-dialog-content>
      <md-field>
        <label>A number</label>
        <md-input type="number" v-model="number" :max="max" />
      </md-field>
    </md-dialog-content>
    ...
</template>
...

Elsewhere, show GuessDialog and pass a value for max:

this.$modal.show(GuessDialog, { max: 42 })
           ...

GitHub