Dialog

API

<template>
<article>
  <veui-button @click="modalOpen = true">
    Modal
  </veui-button>
  <veui-button @click="nonModalOpen = true">
    Non-modal
  </veui-button>
  <veui-dialog
    title="System"
    :open.sync="modalOpen"
    @ok="handleModalClose(true)"
    @cancel="handleModalClose"
  >
    Do you want to refresh the page?
  </veui-dialog>
  <veui-dialog
    title="System"
    :open.sync="nonModalOpen"
    :modal="false"
    @ok="handleModalClose(true)"
    @cancel="handleModalClose"
  >
    Do you want to refresh the page?
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button } from 'veui'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button
  },
  data () {
    return {
      modalOpen: false,
      nonModalOpen: false
    }
  },
  methods: {
    handleModalClose (ok) {
      this.modalOpen = false
      if (ok) {
        location.reload()
      }
    },
    handleNonModalClose (ok) {
      this.nonModalOpen = false
      if (ok) {
        location.reload()
      }
    }
  }
}
</script>

Customized content

<template>
<article>
  <veui-button @click="simpleOpen = true">
    Title & content
  </veui-button>
  <veui-dialog
    :open.sync="simpleOpen"
    title="Customized Title & Content"
    @ok="simpleOpen = false"
    @cancel="simpleOpen = false"
  >
    Customized content via <code>&lt;slot&gt;</code>.
  </veui-dialog>

  <veui-button @click="titleIconOpen = true">
    Icon in Title
  </veui-button>
  <veui-dialog
    :open.sync="titleIconOpen"
    @ok="titleIconOpen = false"
    @cancel="titleIconOpen = false"
  >
    <template slot="title">
      Title with Icon <veui-icon name="top"/>
    </template>
    Customized content via <code>&lt;slot&gt;</code>.
  </veui-dialog>

  <veui-button @click="footOpen = true">
    Foot
  </veui-button>
  <veui-dialog
    :open.sync="footOpen"
    title="Customized Foot"
  >
    Customized content via <code>&lt;slot&gt;</code>.
    <template
      slot="foot"
      slot-scope="{ close }"
    >
      <veui-button
        ui="small primary"
        @click="close('ok')"
      >
        Close
      </veui-button>
    </template>
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button, Icon } from 'veui'
import 'veui-theme-one/icons/top'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button,
    'veui-icon': Icon
  },
  data () {
    return {
      simpleOpen: false,
      titleIconOpen: false,
      footOpen: false
    }
  }
}
</script>

Async support

When you want a unified process to handle all user interactions that might trigger the dialog to be closed, you can leverage the before-close function prop. No matter the close behavior is about to be triggered by clicking “OK”/“Cancel” buttons, the close button or pressing esc, before-close will always take over the following process. If the logic is relatively simple, you can manipulate open prop directly to close the dialog.

<template>
<article>
  <veui-button
    :disabled="submitting"
    @click="submitOpen = true"
  >
    Submit
  </veui-button>
  <veui-button
    :disabled="saving"
    @click="saveOpen = true"
  >
    Save
  </veui-button>
  <veui-dialog
    title="System"
    :open.sync="submitOpen"
    :before-close="submit"
    :closable="false"
    :escapable="!submitting"
  >
    Confirm to create the issue?
    <template
      slot="foot"
      slot-scope="{ close }"
    >
      <veui-button
        ui="primary"
        :loading="submitting"
        @click="close('ok')"
      >
        OK
      </veui-button>
      <veui-button
        :disabled="submitting"
        @click="close"
      >
        Cancel
      </veui-button>
    </template>
  </veui-dialog>
  <veui-dialog
    title="System"
    :open.sync="saveOpen"
    :closable="false"
    :escapable="!submitting"
  >
    Confirm to save the post?
    <template slot="foot">
      <veui-button
        ui="primary"
        :loading="saving"
        @click="save('ok')"
      >
        OK
      </veui-button>
      <veui-button
        :disabled="saving"
        @click="save"
      >
        Cancel
      </veui-button>
    </template>
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button } from 'veui'
import toast from 'veui/managers/toast'

function fakeRequest () {
  return new Promise(resolve =>
    setTimeout(() => {
      resolve(Math.random() < 0.5)
    }, 2000)
  )
}

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button
  },
  data () {
    return {
      submitOpen: false,
      saveOpen: false,
      submitting: false,
      saving: false
    }
  },
  methods: {
    submit (type) {
      if (type === 'ok') {
        this.submitting = true
        return fakeRequest().then(success => {
          this.submitting = false
          if (!success) {
            toast.error('Failed to create the issue. Please retry.')
            return false
          }
          toast.success('Issue created successfully!')
        })
      }
    },
    save (type) {
      if (type === 'ok') {
        this.saving = true
        return fakeRequest().then(success => {
          this.saving = false
          if (!success) {
            toast.error('Failed to save the post. Please retry.')
          } else {
            toast.success('Post saved successfully!')
            this.saveOpen = false
          }
        })
      }
      this.saveOpen = false
    }
  }
}
</script>

Draggable

<template>
<article>
  <veui-button @click="draggableOpen = true">
    Draggable
  </veui-button>
  <veui-dialog
    :open.sync="draggableOpen"
    title="Draggable Dialog"
    draggable
    @ok="draggableOpen = false"
    @cancel="draggableOpen = false"
  >
    This dialog is draggable.
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button } from 'veui'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button
  },
  data () {
    return {
      draggableOpen: false
    }
  }
}
</script>

Stacking order

Open both dialogs and drag one of them to make them overlap a little bit. Then when you activate one dialog, it will be displayed on top of the other one.

<template>
<article>
  <veui-button @click="aOpen = true">
    Dialog A
  </veui-button>
  <veui-dialog
    :open.sync="aOpen"
    title="Dialog A"
    draggable
    :modal="false"
    @ok="aOpen = false"
    @cancel="aOpen = false"
  >
    The content of Dialog A.
  </veui-dialog>

  <veui-button @click="bOpen = true">
    Dialog B
  </veui-button>
  <veui-dialog
    :open.sync="bOpen"
    title="Dialog B"
    draggable
    :modal="false"
    @ok="bOpen = false"
    @cancel="bOpen = false"
  >
    The content of Dialog B.
  </veui-dialog>
</article>
</template>

<script>
import { Dialog, Button } from 'veui'
import 'veui-theme-one/icons/top'

export default {
  components: {
    'veui-dialog': Dialog,
    'veui-button': Button
  },
  data () {
    return {
      aOpen: false,
      bOpen: false
    }
  }
}
</script>

Props

NameTypeDefaultDescription
uistring-

Style variants.

ValueDescription
highCentered horizontally and aligned with the golden ratio point vertically (near to top).
smallSmall (narrow) size with responsive height.
largeLarge (wide) size with responsive height.
autoResponsive width and height according to the content.
modalbooleantrueWhether to display a backdrop to block interactions with the content underneath. Modal dialogs preempt focus by default (will return focus when closed).
titlestring-The title of the dialog. Will be ignored if title slot is specified.
openbooleanfalse

.sync

Whether the dialog is open.

closablebooleantrueWhether to display a close button at the top right corner.
draggablebooleanfalseWhether the dialog is draggable.
escapablebooleanfalseWhether to allow closing the dialog after pressing esc. Only works when closable is set to true.
prioritynumber-The stacking priority of the dialog overlay. See the priority prop of Overlay component.
before-closefunction(string): boolean=|Promise<boolean=>-

Executed when user interaction is about to trigger closing the dialog. The type is function(type: string): boolean=|Promise<boolean=>, where type being the action type of the closing behavior. Available values by default are 'ok'/'cancel'. The return value can be a boolean or a Promise that resolves a boolean value, to handle the situation that an async process is responsible for deciding whether to close the dialog. Will keep the dialog open when returning false or the Promise resolves with false.

<veui-dialog :open.sync="dialogOpen" :before-close="submit">...</veui-dialog>
methods: {
  submit (type) {
    if (type === 'ok') {
      return axios.post('/item/create', {/* ... */})
        .then(({ id, error }) => {
          if (error) {
            this.showError(error)
            return false // resolving `false` will keep the dialog open
          }
        })
    }
    // resolving non-`false` value will close the dialog
  },
  // ...
}
overlay-classstring|Object-The class expression applied to the root element of the dialog overlay. See the overlay-class prop of Overlay component.

Slots

NameDescription
defaultThe content of the dialog.
titleThe title of the dialog. Will ignore the title prop if this slot is specified.
foot

The foot of the dialog. Displays “OK” and “Cancel” buttons by default.

NameTypeDescription
closefunction(type: string): voidThe callback to trigger closing the dialog. type is the action type and will be passed into before-close hook as the first argument. And an event named after type will be triggered synchronously.

Events

NameDescription
okTriggered after the “OK” button is clicked or the dialog is closed with the slot scope function call close('ok').
cancelTriggered after the “Cancel” button or the close button is clicked, or esc is pressed, or the dialog is closed with the slot scope function call close('cancel').
<value>Triggered when the dialog is closed with the slot scope function call close(value).
aftercloseTriggered after the dialog is closed. If leave transition is provided by theme, then afterclose will be triggered when the transition finishes.

Icons

NameDescription
closeClose.