diff --git a/core/src/components/alert/alert-interface.ts b/core/src/components/alert/alert-interface.ts index 9cc650179d9..7dfe782bb3a 100644 --- a/core/src/components/alert/alert-interface.ts +++ b/core/src/components/alert/alert-interface.ts @@ -53,10 +53,12 @@ export type AlertTextareaAttributes = { [key: string]: any }; */ export type AlertInputAttributes = { [key: string]: any }; +type AlertButtonOverlayHandler = boolean | void | { [key: string]: any }; + export interface AlertButton { text: string; role?: 'cancel' | 'destructive' | string; cssClass?: string | string[]; id?: string; - handler?: (value: any) => boolean | void | { [key: string]: any }; + handler?: (value: any) => AlertButtonOverlayHandler | Promise; } diff --git a/core/src/components/alert/alert.tsx b/core/src/components/alert/alert.tsx index 89a13a3d3b6..e07c4951087 100644 --- a/core/src/components/alert/alert.tsx +++ b/core/src/components/alert/alert.tsx @@ -335,24 +335,24 @@ export class Alert implements ComponentInterface, OverlayInterface { forceUpdate(this); } - private buttonClick(button: AlertButton) { + private async buttonClick(button: AlertButton) { const role = button.role; const values = this.getValues(); if (isCancel(role)) { return this.dismiss({ values }, role); } - const returnData = this.callButtonHandler(button, values); + const returnData = await this.callButtonHandler(button, values); if (returnData !== false) { return this.dismiss({ values, ...returnData }, button.role); } - return Promise.resolve(false); + return false; } - private callButtonHandler(button: AlertButton | undefined, data?: any) { + private async callButtonHandler(button: AlertButton | undefined, data?: any) { if (button?.handler) { // a handler has been provided, execute it // pass the handler the values from the inputs - const returnData = safeCall(button.handler, data); + const returnData = await safeCall(button.handler, data); if (returnData === false) { // if the return value of the handler is false then do not dismiss return false; diff --git a/core/src/components/alert/test/basic/alert.e2e.ts b/core/src/components/alert/test/basic/alert.e2e.ts new file mode 100644 index 00000000000..bdb078f9432 --- /dev/null +++ b/core/src/components/alert/test/basic/alert.e2e.ts @@ -0,0 +1,28 @@ +import { expect } from '@playwright/test'; +import { test } from '@utils/test/playwright'; + +test.describe('alert: basic', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/src/components/alert/test/basic'); + }); + + test('should dismiss when async handler resolves', async ({ page }) => { + const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent'); + const ionAlertDidDismiss = await page.spyOnEvent('ionAlertDidDismiss'); + const ionLoadingDidDismiss = await page.spyOnEvent('ionLoadingDidDismiss'); + + const alert = page.locator('ion-alert'); + + await page.click('#asyncHandler'); + await ionAlertDidPresent.next(); + + await page.click('.alert-button'); + + await expect(alert).toBeVisible(); + + await ionLoadingDidDismiss.next(); + await ionAlertDidDismiss.next(); + + await expect(alert).toBeHidden(); + }); +}); diff --git a/core/src/components/alert/test/basic/index.html b/core/src/components/alert/test/basic/index.html index b8675183f54..a1a456bdd3f 100644 --- a/core/src/components/alert/test/basic/index.html +++ b/core/src/components/alert/test/basic/index.html @@ -14,8 +14,9 @@ @@ -30,9 +31,12 @@ Alert Alert Long Message Multiple Buttons (>2) + >Multiple Buttons (>2) + Alert No Message + Alert Async Handler Confirm Prompt Radio @@ -46,6 +50,7 @@ --min-width: 0; --max-width: 200px; } + #delete-button { color: #eb445a; } @@ -351,6 +356,30 @@ ], }); } + + function presentAlertAsyncHandler() { + openAlert({ + header: 'Alert', + message: 'This is an alert with async handlers', + buttons: [ + { + text: 'Confirm', + handler: () => { + return new Promise(async (resolve) => { + const loading = await loadingController.create({ + message: 'Please wait...', + }); + await loading.present(); + setTimeout(async () => { + await loading.dismiss(); + resolve(); + }, 1000); + }); + }, + }, + ], + }); + }