⚠️THIS PROJECT IS LOOKING FOR A MAINTAINER⚠️
Dialogs meet promises in Vue 3 !
This project does not provide any dialogs. Rather, it makes it easy to create your own dialogs and work with them using promises. The dialogs can be opened by calling a function that returns a promise and once the user enters data into the dialog and closes it, the promise resolves with the data the user entered.
let data = await openMyDialog();
npm i vue3-promise-dialog
Showcases the small dialog collection included in this repository as examples :
https://rlemaigre.github.io/vue3-promise-dialog/
A Vite + Vue 3 + Typescript project on Stackblitz featuring a confirm dialog which is probably the simplest use case of the library :
https://stackblitz.com/edit/vitejs-vite-nzzfdg?&terminal=dev
If you need to use a dialog in a parent component, you usually do it by altering its script and template, something along those lines :
<template>
<transition name="...">
<ConfirmDialog v-if="show" @ok="onOk()" @cancel="onCancel()"></ConfirmDialog>
</transition>
</template>
<script>
// Set up a show ref, onOk and onCancel functions. Switch show to true to open the dialog.
</script>
That approach has several disadvantages :
As we all know, requesting data from the server is an asynchronous process that is best handled with promises. For example the Fetch API is a promise based API.
let response = await fetch('http://example.com/movies.json');
Now, just like fetching data from the server, requesting data from the user using a dialog is also an asynchronous process that may complete with a value at some point in the future when the user closes the dialog. Why would the API to fetch data from the user be any different than the API to fetch data from the server ?
Using promises, opening a confirm dialog (for example) is as simple as this :
let ok = await confirm('Are you sure you want to do this ?');
if (ok) {
// Do something
}
The promise resolves to the value the user entered into the dialog when it is closed.
That approach has several advantages :
You may be familiar with the following Vue 2 project : vue-modal-dialog. Unfortunately it hasn't been ported to Vue 3. This repository demonstrates how the basic functionality of that project can be easily recovered in Vue 3.
The core functionality is in the lib
folder.
An example of a small dialog collection built upon the core functionality is in the src/dialogs
folder. It is not
published on NPM since it is dependent on PrimeVue (for buttons and text fields) which you may not be using and the look
and feel you may be aiming for for your own dialogs may differ. Use it as inspiration to build your own dialog
collection.
Your dialogs will open inside a DialogWrapper
component. Include the DialogWrapper
component at the root of your vue
app, after all other content. Internally DialogWrapper
uses a transition tag to transition your dialogs in and out of
view. Use the transitionAttrs
prop to control the transition : the value of that prop will be v-binded as is to the
transition tag inside the wrapper. So for example to set the name of the transition to dialog
,
use :transition-attrs="{name: 'dialog'}"
.
<template>
<div id="app">
<!-- your content -->
<DialogWrapper :transition-attrs="{name: 'dialog'}"/>
</div>
</template>
A dialog is just a standard component that may be transitioned into view. It may be a simple div that you center with
position: fixed. You may add a dark overlay below it to make the div stand out. Whatever. To animate the dialog
appearance and disappearance, use the CSS class names applied by Vue according to the name of the transition defined by
DialogWrapper (dialog
in my example, so dialog-enter-from
, dialog-leave-to
and so on).
To open a dialog X passing it some props, call openDialog(X, props)
. The function will return a promise that will
resolve when the dialog is closed.
let result = await openDialog(MyDialog, myProps);
If you wish to make the call more user-friendly, you may wrap the openDialog function call into another function that hides the details of the dialog component in use. For example, to open a confirm dialog, you may define a confirm
function :
export async function confirm(text: string) {
return await openDialog(ConfirmDialog, {text});
}
let ok = await confirm("Are you sure ?");
Your dialog must define a returnValue
function. You may do so either in the setup function using Composition API or as
a method using Options API. To close the dialog, call closeDialog()
. When you do so, the promise will resolve to the
result of the returnValue
function. You may also resolve the promise to something else (for example null) by passing a
value to closeDialog()
.
The openDialog
function will infer the types of the props and the return type from the component definition. It is
type safe. Your IDE will complain if you pass in a wrong prop or assign the result to a variable of the wrong type.
If using Githubissues.