Skip to content

Commit

Permalink
feat: async confirm dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
joemaylor committed Jan 24, 2025
1 parent 70ec837 commit 7ccfe52
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 6 deletions.
130 changes: 130 additions & 0 deletions apps/showcase/doc/confirmdialog/AsyncDoc.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<template>
<DocSectionText v-bind="$attrs">
<p>The accept callback of a ConfirmDialog can be asynchronous as well. If the accept callback returns a Promise, then the ConfirmDialog will wait for the Promise to resolve before closing the dialog.</p>
<p>While the promise is resolving, the Dialog is locked.</p>
</DocSectionText>
<ConfirmDialog group="async"></ConfirmDialog>
<div class="card flex flex-wrap gap-2 justify-center">
<Button @click="confirm1()" label="Delete"></Button>
</div>
<DocSectionCode :code="code" />
</template>

<script>
export default {
data() {
return {
code: {
basic: `
<ConfirmDialog group="async"></ConfirmDialog>
<Button @click="confirm1()" label="Delete"></Button>
`,
options: `
<template>
<Toast />
<ConfirmDialog group="async"></ConfirmDialog>
<div class="card flex flex-wrap gap-2 justify-center">
<Button @click="confirm1()" label="Delete"></Button>
</div>
</template>
<script>
export default {
methods: {
confirm1() {
this.$confirm.require({
group: 'async',
message: 'Are you sure you want to proceed?',
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
rejectProps: {
label: 'Cancel',
severity: 'secondary',
outlined: true
},
acceptProps: {
label: 'Delete'
},
accept: () => {
this.$toast.add({ severity: 'info', summary: 'Confirmed', detail: 'You have accepted', life: 3000 });
},
reject: () => {
this.$toast.add({ severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000 });
}
});
}
}
};
<\/script>
`,
composition: `
<template>
<Toast />
<ConfirmDialog group="async"></ConfirmDialog>
<div class="card flex flex-wrap gap-2 justify-center">
<Button @click="confirm1()" label="Delete"></Button>
</div>
</template>
<script setup>
import { useConfirm } from "primevue/useconfirm";
import { useToast } from "primevue/usetoast";
const confirm = useConfirm();
const toast = useToast();
const confirm1 = () => {
confirm.require({
group: 'async',
message: 'Are you sure you want to proceed?',
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
rejectProps: {
label: 'Cancel',
severity: 'secondary',
outlined: true
},
acceptProps: {
label: 'Delete'
},
accept: async () => {
await new Promise(resolve => setTimeout(resolve, 2000));
this.$toast.add({ severity: 'info', summary: 'Confirmed', detail: 'You have deleted', life: 3000 });
},
reject: () => {
toast.add({ severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000 });
}
});
};
<\/script>
`
}
};
},
methods: {
confirm1() {
this.$confirm.require({
group: 'async',
message: 'Are you sure you want to proceed?',
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
rejectProps: {
label: 'Cancel',
severity: 'secondary',
outlined: true
},
acceptProps: {
label: 'Delete'
},
accept: async () => {
await new Promise(resolve => setTimeout(resolve, 2000));
this.$toast.add({ severity: 'info', summary: 'Confirmed', detail: 'You have deleted', life: 3000 });
},
reject: () => {
this.$toast.add({ severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000 });
}
});
},
}
};
</script>
6 changes: 6 additions & 0 deletions apps/showcase/pages/confirmdialog/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

<script>
import AccessibilityDoc from '@/doc/confirmdialog/AccessibilityDoc.vue';
import AsyncDoc from '@/doc/confirmdialog/AsyncDoc.vue';
import BasicDoc from '@/doc/confirmdialog/BasicDoc.vue';
import ConfirmationServiceDoc from '@/doc/confirmdialog/ConfirmationServiceDoc.vue';
import HeadlessDoc from '@/doc/confirmdialog/HeadlessDoc.vue';
Expand Down Expand Up @@ -45,6 +46,11 @@ export default {
label: 'Position',
component: PositionDoc
},
{
id: 'async',
label: 'Async',
component: AsyncDoc
},
{
id: 'template',
label: 'Template',
Expand Down
27 changes: 21 additions & 6 deletions packages/primevue/src/confirmdialog/ConfirmDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
:breakpoints="breakpoints"
:closeOnEscape="closeOnEscape"
:draggable="draggable"
:closable="!isAcceptPending"
@update:visible="onHide"
:pt="pt"
:unstyled="unstyled"
>
<template v-if="$slots.container" #container="slotProps">
<slot name="container" :message="confirmation" :closeCallback="slotProps.onclose" :acceptCallback="accept" :rejectCallback="reject" />
<slot name="container" :message="confirmation" :closeCallback="slotProps.onclose" :acceptCallback="accept" :rejectCallback="reject" :isAcceptPending="isAcceptPending" />
</template>
<template v-if="!$slots.container">
<template v-if="!$slots.message">
Expand All @@ -38,14 +39,15 @@
v-bind="confirmation.rejectProps"
:label="rejectLabel"
:pt="ptm('pcRejectButton')"
:disabled="isAcceptPending"
>
<template v-if="rejectIcon || $slots.rejecticon" #icon="iconProps">
<slot name="rejecticon">
<span :class="[rejectIcon, iconProps.class]" v-bind="ptm('pcRejectButton')['icon']" data-pc-section="rejectbuttonicon" />
</slot>
</template>
</Button>
<Button :label="acceptLabel" :class="[cx('pcAcceptButton'), confirmation.acceptClass]" :autofocus="autoFocusAccept" :unstyled="unstyled" @click="accept()" v-bind="confirmation.acceptProps" :pt="ptm('pcAcceptButton')">
<Button :label="acceptLabel" :class="[cx('pcAcceptButton'), confirmation.acceptClass]" :autofocus="autoFocusAccept" :unstyled="unstyled" @click="accept()" v-bind="confirmation.acceptProps" :pt="ptm('pcAcceptButton')" :loading="isAcceptPending">
<template v-if="acceptIcon || $slots.accepticon" #icon="iconProps">
<slot name="accepticon">
<span :class="[acceptIcon, iconProps.class]" v-bind="ptm('pcAcceptButton')['icon']" data-pc-section="acceptbuttonicon" />
Expand All @@ -70,7 +72,9 @@ export default {
data() {
return {
visible: false,
confirmation: null
confirmation: null,
isAcceptPending: false
};
},
mounted() {
Expand Down Expand Up @@ -103,9 +107,20 @@ export default {
ConfirmationEventBus.off('close', this.closeListener);
},
methods: {
accept() {
async accept() {
if (this.confirmation.accept) {
this.confirmation.accept();
const possiblePromise = this.confirmation.accept();
const isPromise = possiblePromise instanceof Promise;
if (isPromise) {
this.isAcceptPending = true;
try {
await possiblePromise;
} finally {
this.isAcceptPending = false;
}
}
}
this.visible = false;
Expand Down Expand Up @@ -178,7 +193,7 @@ export default {
return this.confirmation.defaultFocus === 'reject' ? true : false;
},
closeOnEscape() {
return this.confirmation ? this.confirmation.closeOnEscape : true;
return this.isAcceptPending ? false : this.confirmation ? this.confirmation.closeOnEscape : true;
}
},
components: {
Expand Down

0 comments on commit 7ccfe52

Please sign in to comment.