mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +08:00
feat(alert): accept Promise for button handler (#25702)
Resolves #25700 Co-authored-by: Sean Perkins <sean@ionic.io>
This commit is contained in:
@ -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<AlertButtonOverlayHandler>;
|
||||
}
|
||||
|
@ -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;
|
||||
|
28
core/src/components/alert/test/basic/alert.e2e.ts
Normal file
28
core/src/components/alert/test/basic/alert.e2e.ts
Normal file
@ -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();
|
||||
});
|
||||
});
|
@ -14,8 +14,9 @@
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
</head>
|
||||
<script type="module">
|
||||
import { alertController } from '../../../../dist/ionic/index.esm.js';
|
||||
import { alertController, loadingController } from '../../../../dist/ionic/index.esm.js';
|
||||
window.alertController = alertController;
|
||||
window.loadingController = loadingController;
|
||||
</script>
|
||||
|
||||
<body>
|
||||
@ -30,9 +31,12 @@
|
||||
<ion-button id="basic" expand="block" onclick="presentAlert()">Alert</ion-button>
|
||||
<ion-button id="longMessage" expand="block" onclick="presentAlertLongMessage()">Alert Long Message</ion-button>
|
||||
<ion-button id="multipleButtons" expand="block" onclick="presentAlertMultipleButtons()"
|
||||
>Multiple Buttons (>2)</ion-button
|
||||
>
|
||||
>Multiple Buttons (>2)
|
||||
</ion-button>
|
||||
<ion-button id="noMessage" expand="block" onclick="presentAlertNoMessage()">Alert No Message</ion-button>
|
||||
<ion-button id="asyncHandler" expand="block" onclick="presentAlertAsyncHandler()"
|
||||
>Alert Async Handler</ion-button
|
||||
>
|
||||
<ion-button id="confirm" expand="block" onclick="presentAlertConfirm()">Confirm</ion-button>
|
||||
<ion-button id="prompt" expand="block" onclick="presentAlertPrompt()">Prompt</ion-button>
|
||||
<ion-button id="radio" expand="block" onclick="presentAlertRadio()">Radio</ion-button>
|
||||
@ -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);
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user