vue-nice-modal is a utility library that converts Vue.js modal components into a Promise-based API.
Inspired By @ebay/nice-modal-react and vant.
Support for Vue 2.x via vue-demi
English | 简体中文 |
You can see a list of examples at: examples/*
folder.
npm install vue-nice-modal
# or
yarn add vue-nice-modal
# or
pnpm add vue-nice-modal
import { create } from 'vue-nice-modal';
import MyModal from './MyModal.vue';
const myModal = create(MyModal);
myModal
.show({
title: 'Hello, world!',
content: 'This is a nice modal.',
})
.then((result) => {
console.log('Confirmed! Result:', result);
})
.catch((error) => {
console.error('Rejected! Error:', error);
});
<script setup lang="ts">
import { Dialog } from 'vant';
import { INiceModalHandlers } from 'vue-nice-modal';
// inject hide/remove/callback methods by vue-nice-modal
interface IProps extends INiceModalHandlers<number> {
visible: boolean;
// props you need
title: string;
content: string;
}
interface IEmits {
(e: 'update:visible', visible: boolean): void;
}
const props = defineProps<IProps>();
// @ts-ignore
const emit = defineEmits<IEmits>();
const handleCancel = () => {
props.hide(); // or emit('update:visible', false)
props.callback('cancel'); // reject the promise
};
const handleConfirm = async () => {
// mock async function call
const sleep = (ms: number): Promise<number> =>
new Promise((res) =>
setTimeout(() => {
res(ms);
}, ms)
);
const payload = await sleep(1000);
// resolve the promise with payload
props.callback('confirm', payload);
};
</script>
<template>
<Dialog
:show="visible"
@update:show="$emit('update:visible', false)"
@cancel="handleCancel"
@confirm="handleConfirm"
@closed="remove"
:title="title"
:content="content"
show-cancel-button
class="demo-dialog"
>
<div>Hello,Vue Nice Modal</div>
</Dialog>
</template>
import { createApp } from 'vue';
import { VueNiceModalPluginForVue3 } from 'vue-nice-modal';
import App from './App.vue';
const app = createApp(App);
app.use(VueNiceModalPluginForVue3);
app.mount('#app');
Vue Nice Modal creates a new Vue application instance internally and mounts the user-created component to that instance. This allows it to run properly inside a modal without conflicting with the state and logic of the main application.
However, if you need to access data or methods from the main application inside the modal, you can use the plugin to achieve shared context.
you can differentiate between multiple applications by passing a appKey as an option in the plugin options and passing it when creating the modal instance.
app.use(VueNiceModalPluginForVue3, { appKey: 'another app key' });
create(MyModal, 'another app key');
The create function takes a Vue.js component and returns a Modal object with the following methods:
Shows the modal component and returns a Promise that resolves if the user confirms the modal, or rejects if the user cancels it.
The options parameter is an object that should contain the props that are relevant to the modal component(Excluding the common properties and methods injected by vue-nice-modal, only include custom properties required by the component itself). The ComponentProps and INiceModalHandlers types are used to ensure that the options object is properly typed and that any errors related to prop usage are caught at compile-time.
Here’s how the show method’s type hinting is implemented:
type ComponentProps<C extends Component> = C extends new (...args: any) => any
? Omit<
InstanceType<C>['$props'],
keyof VNodeProps | keyof AllowedComponentProps
>
: never;
type ExtractOptions<T extends Record<string, any>> = Omit<
T,
keyof INiceModalHandlers | 'visible' | 'onUpdate:visible'
>;
export function create<C extends Component>(Comp: C) {
// ...
const show = (options: ExtractOptions<ComponentProps<C>>) => {
// ...
};
return {
show,
// ...
};
}
Hides the modal component.
Removes the modal component from the DOM.
vue-nice-modal provides some TypeScript type definitions:
The Modal interface defines the methods of the object returned by create.
interface Modal {
show: (options: ExtractOptions<ComponentProps<C>>) => Promise<any>;
hide: () => void;
remove: () => void;
}
The ComponentProps type defines the props of a Vue.js component.
type ComponentProps<C extends Component> = C extends new (...args: any) => any
? Omit<
InstanceType<C>['$props'],
keyof VNodeData | keyof AllowedComponentProps
>
: never;
The INiceModalHandlers interface defines the methods that are used to handle the user’s confirmation or cancellation of the modal.
export interface INiceModalHandlers<T = any> {
callback: (action: 'confirm' | 'cancel', payload?: T) => void;
remove: () => void;
hide: () => void;
}
These methods, as well as visible and update:visible event, will be injected into the user’s custom modal component, and even if not using Promise-based function calls, related props can be passed in based on v-model(visible and update:visible) to control the visibility of the component. This allows users to control the display and hiding of the modal component in their own preferred way, while also ensuring the flexibility of the vue-nice-modal library
The ExtractOptions type is used to extract the options that are relevant to the modal component(Excluding the common properties and methods injected by vue-nice-modal, only include custom properties required by the component itself).
type ExtractOptions<T extends Record<string, any>> = Omit<
T,
keyof INiceModalHandlers | 'visible' | 'onUpdate:visible'
>;