feat(modal): data and role are passed to canDismiss (#26384)

resolves #26292
This commit is contained in:
Liam DeBeasi
2022-12-02 10:46:41 -05:00
committed by GitHub
parent 5d035abdb0
commit 1b30fc97d3
7 changed files with 66 additions and 17 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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' });
});
});
});