Skip to content

Instantly share code, notes, and snippets.

@wobsoriano
Last active July 17, 2022 15:43
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wobsoriano/1e63708d7771c34f835c0f6e3c5e731a to your computer and use it in GitHub Desktop.
Save wobsoriano/1e63708d7771c34f835c0f6e3c5e731a to your computer and use it in GitHub Desktop.
Vuetify + Composition API Dialog component that can be used globally
<template>
<div v-frag>
<slot />
<v-dialog
v-model="isOpen"
:max-width="options.width"
:persistent="options.persistent"
>
<v-card>
<v-card-title>{{ title }}</v-card-title>
<v-card-text v-show="!!content">{{ content }}</v-card-text>
<v-card-actions class="pt-0">
<v-spacer></v-spacer>
<v-btn
v-show="!!options.showCancel"
color="primary"
text
@click="cancel"
>Cancel</v-btn
>
<v-btn color="primary" text @click="agree">Yes</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script lang="ts">
import frag from 'vue-frag';
import {
defineComponent,
provide,
reactive,
toRefs,
} from '@nuxtjs/composition-api';
import {
CreateConfirmDialogKey,
CreateConfirmDialogOptions,
} from '~/composables';
export default defineComponent({
directives: {
frag,
},
setup() {
const state = reactive({
isOpen: false,
resolve: (_val: boolean) => {},
reject: (_val: boolean) => {},
content: '',
title: '',
options: {
width: 300,
showCancel: true,
persistent: false,
} as CreateConfirmDialogOptions,
});
const createConfirmDialog = (
title: string,
content: string,
options: CreateConfirmDialogOptions = {}
) => {
state.isOpen = true;
state.title = title;
state.content = content;
state.options = Object.assign(state.options, options);
return new Promise<boolean>((resolve, reject) => {
state.resolve = resolve;
state.reject = reject;
});
};
provide(CreateConfirmDialogKey, createConfirmDialog);
const agree = () => {
state.resolve(true);
state.isOpen = false;
};
const cancel = () => {
state.resolve(false);
state.isOpen = false;
};
return {
...toRefs(state),
agree,
cancel,
};
},
});
</script>
<template>
<v-app>
<v-main>
<v-container>
<DialogProvider>
<Nuxt />
</DialogProvider>
</v-container>
</v-main>
</v-app>
</template>
<script lang="ts">
import { defineComponent } from '@nuxtjs/composition-api';
import DialogProvider from '~/components/DialogProvider.vue';
export default defineComponent({
components: {
DialogProvider,
}
});
</script>
<script lang="ts">
import { defineComponent } from '@nuxtjs/composition-api';
import { useDialog } from '~/composables';
export default defineComponent({
setup() {
const createConfirmDialog = useDialog();
const handleDelete = async () => {
try {
const shouldProceed = await createConfirmDialog(
'Confirm',
'Delete this post?',
{ width: 300 }
);
if (shouldProceed) {
// delete post
}
} catch (_e) {}
};
return {
handleDelete
};
},
});
</script>
import { inject, InjectionKey } from '@nuxtjs/composition-api';
export interface CreateConfirmDialogOptions {
width?: string | number;
showCancel?: boolean;
persistent?: boolean;
}
export type CreateConfirmDialog = (
title: string,
content: string,
options: CreateConfirmDialogOptions
) => Promise<boolean>;
export const CreateConfirmDialogKey: InjectionKey<CreateConfirmDialog> = Symbol(
'CreateConfirmDialogKey'
);
export function useDialog() {
const dialog = inject(CreateConfirmDialogKey);
if (!dialog) {
throw new Error('Could not resolve provider');
}
return dialog;
}
@some-user123
Copy link

some-user123 commented Jan 5, 2022

I think in line 22 of useDialog.ts
if (!confirm) {
should be replaced with
if (!dialog) { .

@wobsoriano
Copy link
Author

Thanks @some-user123 !

@Sjoerd82
Copy link

Could you provide us with a JS version, for those that are not on TS (yet)..?

@wobsoriano
Copy link
Author

@Sjoerd82 sure, will take a look tomorrow

@pglaudemans
Copy link

Hi wobsoriano, do you have a pen with a working example? Much appreciated!
cheers, Patrick

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment