mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +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 };
|
export type AlertInputAttributes = { [key: string]: any };
|
||||||
|
|
||||||
|
type AlertButtonOverlayHandler = boolean | void | { [key: string]: any };
|
||||||
|
|
||||||
export interface AlertButton {
|
export interface AlertButton {
|
||||||
text: string;
|
text: string;
|
||||||
role?: 'cancel' | 'destructive' | string;
|
role?: 'cancel' | 'destructive' | string;
|
||||||
cssClass?: string | string[];
|
cssClass?: string | string[];
|
||||||
id?: 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);
|
forceUpdate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private buttonClick(button: AlertButton) {
|
private async buttonClick(button: AlertButton) {
|
||||||
const role = button.role;
|
const role = button.role;
|
||||||
const values = this.getValues();
|
const values = this.getValues();
|
||||||
if (isCancel(role)) {
|
if (isCancel(role)) {
|
||||||
return this.dismiss({ values }, role);
|
return this.dismiss({ values }, role);
|
||||||
}
|
}
|
||||||
const returnData = this.callButtonHandler(button, values);
|
const returnData = await this.callButtonHandler(button, values);
|
||||||
if (returnData !== false) {
|
if (returnData !== false) {
|
||||||
return this.dismiss({ values, ...returnData }, button.role);
|
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) {
|
if (button?.handler) {
|
||||||
// a handler has been provided, execute it
|
// a handler has been provided, execute it
|
||||||
// pass the handler the values from the inputs
|
// 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 (returnData === false) {
|
||||||
// if the return value of the handler is false then do not dismiss
|
// if the return value of the handler is false then do not dismiss
|
||||||
return false;
|
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>
|
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { alertController } from '../../../../dist/ionic/index.esm.js';
|
import { alertController, loadingController } from '../../../../dist/ionic/index.esm.js';
|
||||||
window.alertController = alertController;
|
window.alertController = alertController;
|
||||||
|
window.loadingController = loadingController;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -30,9 +31,12 @@
|
|||||||
<ion-button id="basic" expand="block" onclick="presentAlert()">Alert</ion-button>
|
<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="longMessage" expand="block" onclick="presentAlertLongMessage()">Alert Long Message</ion-button>
|
||||||
<ion-button id="multipleButtons" expand="block" onclick="presentAlertMultipleButtons()"
|
<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="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="confirm" expand="block" onclick="presentAlertConfirm()">Confirm</ion-button>
|
||||||
<ion-button id="prompt" expand="block" onclick="presentAlertPrompt()">Prompt</ion-button>
|
<ion-button id="prompt" expand="block" onclick="presentAlertPrompt()">Prompt</ion-button>
|
||||||
<ion-button id="radio" expand="block" onclick="presentAlertRadio()">Radio</ion-button>
|
<ion-button id="radio" expand="block" onclick="presentAlertRadio()">Radio</ion-button>
|
||||||
@ -46,6 +50,7 @@
|
|||||||
--min-width: 0;
|
--min-width: 0;
|
||||||
--max-width: 200px;
|
--max-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#delete-button {
|
#delete-button {
|
||||||
color: #eb445a;
|
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>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Reference in New Issue
Block a user