mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(modal): data and role are passed to canDismiss (#26384)
resolves #26292
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { GESTURE } from '@utils/overlays';
|
||||
|
||||
import type { Animation } from '../../../interface';
|
||||
|
||||
export const handleCanDismiss = async (el: HTMLIonModalElement, animation: Animation) => {
|
||||
@@ -18,7 +20,7 @@ export const handleCanDismiss = async (el: HTMLIonModalElement, animation: Anima
|
||||
* If the function returns `true`,
|
||||
* then we can proceed with dismiss.
|
||||
*/
|
||||
const shouldDismiss = await el.canDismiss();
|
||||
const shouldDismiss = await el.canDismiss(undefined, GESTURE);
|
||||
if (!shouldDismiss) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,15 @@ import type { Attributes } from '../../utils/helpers';
|
||||
import { KEYBOARD_DID_OPEN } from '../../utils/keyboard/keyboard';
|
||||
import { printIonWarning } from '../../utils/logging';
|
||||
import { Style as StatusBarStyle, StatusBar } from '../../utils/native/status-bar';
|
||||
import { BACKDROP, activeAnimations, dismiss, eventMethod, prepareOverlay, present } from '../../utils/overlays';
|
||||
import {
|
||||
GESTURE,
|
||||
BACKDROP,
|
||||
activeAnimations,
|
||||
dismiss,
|
||||
eventMethod,
|
||||
prepareOverlay,
|
||||
present,
|
||||
} from '../../utils/overlays';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
import { deepReady } from '../../utils/transition';
|
||||
|
||||
@@ -267,7 +275,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
* If the value is `true` or the value's function returns `true`, the modal will close when trying to dismiss.
|
||||
* If the value is `false` or the value's function returns `false`, the modal will not close when trying to dismiss.
|
||||
*/
|
||||
@Prop() canDismiss?: undefined | boolean | (() => Promise<boolean>);
|
||||
@Prop() canDismiss?: undefined | boolean | ((data?: any, role?: string) => Promise<boolean>);
|
||||
|
||||
/**
|
||||
* Emitted after the modal has presented.
|
||||
@@ -449,7 +457,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
* modal is allowed to dismiss based
|
||||
* on the state of the canDismiss prop.
|
||||
*/
|
||||
private async checkCanDismiss() {
|
||||
private async checkCanDismiss(data?: any, role?: string) {
|
||||
const { canDismiss } = this;
|
||||
|
||||
/**
|
||||
@@ -461,7 +469,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
|
||||
if (typeof canDismiss === 'function') {
|
||||
return canDismiss();
|
||||
return canDismiss(data, role);
|
||||
}
|
||||
|
||||
return canDismiss;
|
||||
@@ -603,7 +611,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
*/
|
||||
this.gestureAnimationDismissing = true;
|
||||
this.animation!.onFinish(async () => {
|
||||
await this.dismiss(undefined, 'gesture');
|
||||
await this.dismiss(undefined, GESTURE);
|
||||
this.gestureAnimationDismissing = false;
|
||||
});
|
||||
});
|
||||
@@ -665,7 +673,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
this.animation!.onFinish(async () => {
|
||||
this.currentBreakpoint = 0;
|
||||
this.ionBreakpointDidChange.emit({ breakpoint: this.currentBreakpoint });
|
||||
await this.dismiss(undefined, 'gesture');
|
||||
await this.dismiss(undefined, GESTURE);
|
||||
this.gestureAnimationDismissing = false;
|
||||
});
|
||||
}
|
||||
@@ -678,7 +686,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
*/
|
||||
@Method()
|
||||
async dismiss(data?: any, role?: string): Promise<boolean> {
|
||||
if (this.gestureAnimationDismissing && role !== 'gesture') {
|
||||
if (this.gestureAnimationDismissing && role !== GESTURE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -687,7 +695,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
* for calling the dismiss method, we should
|
||||
* not run the canDismiss check again.
|
||||
*/
|
||||
if (role !== 'handler' && !(await this.checkCanDismiss())) {
|
||||
if (role !== 'handler' && !(await this.checkCanDismiss(data, role))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,13 +116,13 @@
|
||||
handler = false;
|
||||
break;
|
||||
case 'promise-true':
|
||||
handler = () => {
|
||||
handler = (data, role) => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(true);
|
||||
|
||||
setTimeout(() => {
|
||||
const event = new CustomEvent('ionHandlerDone');
|
||||
const event = new CustomEvent('ionHandlerDone', { detail: { data, role } });
|
||||
window.dispatchEvent(event);
|
||||
}, 1000);
|
||||
}, 250);
|
||||
@@ -132,11 +132,11 @@
|
||||
case 'promise-false':
|
||||
handler = () => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
setTimeout((data, role) => {
|
||||
resolve(false);
|
||||
|
||||
setTimeout(() => {
|
||||
const event = new CustomEvent('ionHandlerDone');
|
||||
const event = new CustomEvent('ionHandlerDone', { detail: { data, role } });
|
||||
window.dispatchEvent(event);
|
||||
}, 1000);
|
||||
}, 250);
|
||||
|
||||
@@ -378,4 +378,42 @@ test.describe('modal: canDismiss', () => {
|
||||
await ionModalDidDismiss.next();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('function params', () => {
|
||||
test.beforeEach(({ skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('md');
|
||||
});
|
||||
test('should pass data and role when calling dismiss', async ({ page }) => {
|
||||
const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
|
||||
const ionHandlerDone = await page.spyOnEvent('ionHandlerDone');
|
||||
|
||||
await page.click('#radio-promise-true');
|
||||
await page.click('#show-modal');
|
||||
|
||||
await ionModalDidPresent.next();
|
||||
|
||||
const modal = await page.locator('ion-modal');
|
||||
await modal.evaluate((el: HTMLIonModalElement) => el.dismiss('my data', 'my role'));
|
||||
|
||||
await ionHandlerDone.next();
|
||||
await expect(ionHandlerDone).toHaveReceivedEventDetail({ data: 'my data', role: 'my role' });
|
||||
});
|
||||
test('should pass data and role when swiping', async ({ page }) => {
|
||||
const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
|
||||
const ionHandlerDone = await page.spyOnEvent('ionHandlerDone');
|
||||
|
||||
await page.click('#radio-card');
|
||||
await page.click('#radio-promise-true');
|
||||
await page.click('#show-modal');
|
||||
|
||||
await ionModalDidPresent.next();
|
||||
|
||||
const modalHeader = await page.locator('#modal-header');
|
||||
await dragElementBy(modalHeader, page, 0, 500);
|
||||
|
||||
await ionHandlerDone.next();
|
||||
await expect(ionHandlerDone).toHaveReceivedEventDetail({ data: undefined, role: 'gesture' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user