mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-17 18:54:11 +08:00
feat(popover): add ability to pass event to present method (#23827)
resolves #23813
This commit is contained in:
@ -887,7 +887,7 @@ ion-popover,prop,triggerAction,"click" | "context-menu" | "hover",'click',false,
|
|||||||
ion-popover,method,dismiss,dismiss(data?: any, role?: string | undefined, dismissParentPopover?: boolean) => Promise<boolean>
|
ion-popover,method,dismiss,dismiss(data?: any, role?: string | undefined, dismissParentPopover?: boolean) => Promise<boolean>
|
||||||
ion-popover,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
ion-popover,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||||
ion-popover,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
ion-popover,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||||
ion-popover,method,present,present() => Promise<void>
|
ion-popover,method,present,present(event?: MouseEvent | TouchEvent | PointerEvent | undefined) => Promise<void>
|
||||||
ion-popover,event,didDismiss,OverlayEventDetail<any>,true
|
ion-popover,event,didDismiss,OverlayEventDetail<any>,true
|
||||||
ion-popover,event,didPresent,void,true
|
ion-popover,event,didPresent,void,true
|
||||||
ion-popover,event,ionPopoverDidDismiss,OverlayEventDetail<any>,true
|
ion-popover,event,ionPopoverDidDismiss,OverlayEventDetail<any>,true
|
||||||
|
4
core/src/components.d.ts
vendored
4
core/src/components.d.ts
vendored
@ -1829,9 +1829,9 @@ export namespace Components {
|
|||||||
"onWillDismiss": <T = any>() => Promise<OverlayEventDetail<T>>;
|
"onWillDismiss": <T = any>() => Promise<OverlayEventDetail<T>>;
|
||||||
"overlayIndex": number;
|
"overlayIndex": number;
|
||||||
/**
|
/**
|
||||||
* Present the popover overlay after it has been created.
|
* Present the popover overlay after it has been created. Developers can pass a mouse, touch, or pointer event to position the popover relative to where that event was dispatched.
|
||||||
*/
|
*/
|
||||||
"present": () => Promise<void>;
|
"present": (event?: MouseEvent | TouchEvent | PointerEvent | undefined) => Promise<void>;
|
||||||
/**
|
/**
|
||||||
* When opening a popover from a trigger, we should not be modifying the `event` prop from inside the component. Additionally, when pressing the "Right" arrow key, we need to shift focus to the first descendant in the newly presented popover.
|
* When opening a popover from a trigger, we should not be modifying the `event` prop from inside the component. Additionally, when pressing the "Right" arrow key, we need to shift focus to the first descendant in the newly presented popover.
|
||||||
*/
|
*/
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Mode } from '../../interface';
|
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Mode, OverlayInterface } from '../../interface';
|
||||||
|
|
||||||
|
export interface PopoverInterface extends OverlayInterface {
|
||||||
|
present: (event?: MouseEvent | TouchEvent | PointerEvent) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PopoverOptions<T extends ComponentRef = ComponentRef> {
|
export interface PopoverOptions<T extends ComponentRef = ComponentRef> {
|
||||||
component: T;
|
component: T;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, State, Watch, h } from '@stencil/core';
|
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, State, Watch, h } from '@stencil/core';
|
||||||
|
|
||||||
import { getIonMode } from '../../global/ionic-global';
|
import { getIonMode } from '../../global/ionic-global';
|
||||||
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, OverlayEventDetail, OverlayInterface, PopoverSize, PositionAlign, PositionReference, PositionSide, TriggerAction } from '../../interface';
|
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, OverlayEventDetail, PopoverInterface, PopoverSize, PositionAlign, PositionReference, PositionSide, TriggerAction } from '../../interface';
|
||||||
import { CoreDelegate, attachComponent, detachComponent } from '../../utils/framework-delegate';
|
import { CoreDelegate, attachComponent, detachComponent } from '../../utils/framework-delegate';
|
||||||
import { addEventListener, raf } from '../../utils/helpers';
|
import { addEventListener, raf } from '../../utils/helpers';
|
||||||
import { BACKDROP, dismiss, eventMethod, focusFirstDescendant, prepareOverlay, present } from '../../utils/overlays';
|
import { BACKDROP, dismiss, eventMethod, focusFirstDescendant, prepareOverlay, present } from '../../utils/overlays';
|
||||||
@ -32,7 +32,7 @@ import { configureDismissInteraction, configureKeyboardInteraction, configureTri
|
|||||||
},
|
},
|
||||||
shadow: true
|
shadow: true
|
||||||
})
|
})
|
||||||
export class Popover implements ComponentInterface, OverlayInterface {
|
export class Popover implements ComponentInterface, PopoverInterface {
|
||||||
|
|
||||||
private usersElement?: HTMLElement;
|
private usersElement?: HTMLElement;
|
||||||
private triggerEl?: HTMLElement | null;
|
private triggerEl?: HTMLElement | null;
|
||||||
@ -48,7 +48,6 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
|||||||
private inline = false;
|
private inline = false;
|
||||||
private workingDelegate?: FrameworkDelegate;
|
private workingDelegate?: FrameworkDelegate;
|
||||||
|
|
||||||
private triggerEv?: Event;
|
|
||||||
private focusDescendantOnPresent = false;
|
private focusDescendantOnPresent = false;
|
||||||
|
|
||||||
lastFocus?: HTMLElement;
|
lastFocus?: HTMLElement;
|
||||||
@ -305,12 +304,10 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
|||||||
*/
|
*/
|
||||||
@Method()
|
@Method()
|
||||||
async presentFromTrigger(event?: any, focusDescendant = false) {
|
async presentFromTrigger(event?: any, focusDescendant = false) {
|
||||||
this.triggerEv = event;
|
|
||||||
this.focusDescendantOnPresent = focusDescendant;
|
this.focusDescendantOnPresent = focusDescendant;
|
||||||
|
|
||||||
await this.present();
|
await this.present(event);
|
||||||
|
|
||||||
this.triggerEv = undefined;
|
|
||||||
this.focusDescendantOnPresent = false;
|
this.focusDescendantOnPresent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,9 +346,12 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Present the popover overlay after it has been created.
|
* Present the popover overlay after it has been created.
|
||||||
|
* Developers can pass a mouse, touch, or pointer event
|
||||||
|
* to position the popover relative to where that event
|
||||||
|
* was dispatched.
|
||||||
*/
|
*/
|
||||||
@Method()
|
@Method()
|
||||||
async present(): Promise<void> {
|
async present(event?: MouseEvent | TouchEvent | PointerEvent): Promise<void> {
|
||||||
if (this.presented) {
|
if (this.presented) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -381,7 +381,7 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
|||||||
this.configureDismissInteraction();
|
this.configureDismissInteraction();
|
||||||
|
|
||||||
this.currentTransition = present(this, 'popoverEnter', iosEnterAnimation, mdEnterAnimation, {
|
this.currentTransition = present(this, 'popoverEnter', iosEnterAnimation, mdEnterAnimation, {
|
||||||
event: this.event || this.triggerEv,
|
event: event || this.event,
|
||||||
size: this.size,
|
size: this.size,
|
||||||
trigger: this.triggerEl,
|
trigger: this.triggerEl,
|
||||||
reference: this.reference,
|
reference: this.reference,
|
||||||
|
@ -577,9 +577,12 @@ Type: `Promise<OverlayEventDetail<T>>`
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
### `present() => Promise<void>`
|
### `present(event?: MouseEvent | TouchEvent | PointerEvent | undefined) => Promise<void>`
|
||||||
|
|
||||||
Present the popover overlay after it has been created.
|
Present the popover overlay after it has been created.
|
||||||
|
Developers can pass a mouse, touch, or pointer event
|
||||||
|
to position the popover relative to where that event
|
||||||
|
was dispatched.
|
||||||
|
|
||||||
#### Returns
|
#### Returns
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { newE2EPage } from '@stencil/core/testing';
|
import { newE2EPage } from '@stencil/core/testing';
|
||||||
|
|
||||||
test('popover: inline', async () => {
|
test('popover: inline, isOpen and event props', async () => {
|
||||||
const page = await newE2EPage({ url: '/src/components/popover/test/inline?ionic:_testing=true' });
|
const page = await newE2EPage({ url: '/src/components/popover/test/inline?ionic:_testing=true' });
|
||||||
const screenshotCompares = [];
|
const screenshotCompares = [];
|
||||||
|
|
||||||
await page.click('ion-button');
|
await page.click('ion-button#props');
|
||||||
await page.waitForSelector('ion-popover');
|
await page.waitForSelector('ion-popover');
|
||||||
|
|
||||||
let popover = await page.find('ion-popover');
|
let popover = await page.find('ion-popover');
|
||||||
@ -21,7 +21,43 @@ test('popover: inline', async () => {
|
|||||||
|
|
||||||
popover = await page.find('ion-popover');
|
popover = await page.find('ion-popover');
|
||||||
|
|
||||||
await page.click('ion-button');
|
await page.click('ion-button#props');
|
||||||
|
await page.waitForSelector('ion-popover');
|
||||||
|
|
||||||
|
let popoverAgain = await page.find('ion-popover');
|
||||||
|
|
||||||
|
expect(popoverAgain).not.toBe(null);
|
||||||
|
await popoverAgain.waitForVisible();
|
||||||
|
|
||||||
|
screenshotCompares.push(await page.compareScreenshot());
|
||||||
|
|
||||||
|
for (const screenshotCompare of screenshotCompares) {
|
||||||
|
expect(screenshotCompare).toMatchScreenshot();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('popover: inline, present method', async () => {
|
||||||
|
const page = await newE2EPage({ url: '/src/components/popover/test/inline?ionic:_testing=true' });
|
||||||
|
const screenshotCompares = [];
|
||||||
|
|
||||||
|
await page.click('ion-button#method');
|
||||||
|
await page.waitForSelector('ion-popover');
|
||||||
|
|
||||||
|
let popover = await page.find('ion-popover');
|
||||||
|
|
||||||
|
expect(popover).not.toBe(null);
|
||||||
|
await popover.waitForVisible();
|
||||||
|
|
||||||
|
screenshotCompares.push(await page.compareScreenshot());
|
||||||
|
|
||||||
|
await popover.callMethod('dismiss');
|
||||||
|
await popover.waitForNotVisible();
|
||||||
|
|
||||||
|
screenshotCompares.push(await page.compareScreenshot('dismiss'));
|
||||||
|
|
||||||
|
popover = await page.find('ion-popover');
|
||||||
|
|
||||||
|
await page.click('ion-button#method');
|
||||||
await page.waitForSelector('ion-popover');
|
await page.waitForSelector('ion-popover');
|
||||||
|
|
||||||
let popoverAgain = await page.find('ion-popover');
|
let popoverAgain = await page.find('ion-popover');
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content class="ion-padding">
|
<ion-content class="ion-padding">
|
||||||
<ion-button onclick="openPopover(event)">Open Popover</ion-button>
|
<ion-button id="props" onclick="openPopover(event)">Open Popover via Props</ion-button>
|
||||||
|
<ion-button id="method" onclick="openPopoverMethod(event)">Open Popover via Present Method</ion-button>
|
||||||
|
|
||||||
<ion-popover>
|
<ion-popover>
|
||||||
<ion-content class="ion-padding">
|
<ion-content class="ion-padding">
|
||||||
@ -35,6 +36,10 @@
|
|||||||
popover.event = ev;
|
popover.event = ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const openPopoverMethod = (ev) => {
|
||||||
|
popover.present(ev);
|
||||||
|
}
|
||||||
|
|
||||||
popover.addEventListener('didDismiss', () => {
|
popover.addEventListener('didDismiss', () => {
|
||||||
popover.isOpen = false;
|
popover.isOpen = false;
|
||||||
popover.event = undefined;
|
popover.event = undefined;
|
||||||
|
Reference in New Issue
Block a user