mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 10:01:59 +08:00
fix(vue): account for event name changes in vue 3.0.6+ for overlay components (#23100)
This commit is contained in:
@ -1,8 +1,7 @@
|
||||
import { App, Plugin } from 'vue';
|
||||
import { IonicConfig, setupConfig } from '@ionic/core';
|
||||
import { applyPolyfills, defineCustomElements } from '@ionic/core/loader';
|
||||
|
||||
const needsKebabCase = (version: string) => !['3.0.0', '3.0.1', '3.0.2', '3.0.3', '3.0.4', '3.0.5'].includes(version);
|
||||
import { needsKebabCase } from './utils';
|
||||
|
||||
/**
|
||||
* We need to make sure that the web component fires an event
|
||||
|
@ -57,3 +57,5 @@ export const getConfig = (): CoreConfig | null => {
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const needsKebabCase = (version: string) => !['3.0.0', '3.0.1', '3.0.2', '3.0.3', '3.0.4', '3.0.5'].includes(version);
|
||||
|
@ -1,20 +1,37 @@
|
||||
import { defineComponent, h, ref, VNode } from 'vue';
|
||||
import { defineComponent, h, ref, VNode, getCurrentInstance } from 'vue';
|
||||
import { needsKebabCase } from '../utils';
|
||||
|
||||
export interface OverlayProps {
|
||||
isOpen?: boolean;
|
||||
}
|
||||
|
||||
export const defineOverlayContainer = <Props extends object>(name: string, componentProps: string[] = [], controller: any) => {
|
||||
// TODO
|
||||
/**
|
||||
* Vue 3.0.6 fixed a bug where events on custom elements
|
||||
* were always converted to lower case, so "ionRefresh"
|
||||
* became "ionRefresh". We need to account for the old
|
||||
* issue as well as the new behavior where "ionRefresh"
|
||||
* is converted to "ion-refresh".
|
||||
* See https://github.com/vuejs/vue-next/pull/2847
|
||||
*/
|
||||
const eventPrefix = name.toLowerCase().split('-').join('');
|
||||
const eventListeners = [
|
||||
const lowerCaseListeners = [
|
||||
{ componentEv: `${eventPrefix}willpresent`, frameworkEv: 'onWillPresent' },
|
||||
{ componentEv: `${eventPrefix}didpresent`, frameworkEv: 'onDidPresent' },
|
||||
{ componentEv: `${eventPrefix}willdismiss`, frameworkEv: 'onWillDismiss' },
|
||||
{ componentEv: `${eventPrefix}diddismiss`, frameworkEv: 'onDidDismiss' },
|
||||
];
|
||||
const kebabCaseListeners = [
|
||||
{ componentEv: `${name}-will-present`, frameworkEv: 'onWillPresent' },
|
||||
{ componentEv: `${name}-did-present`, frameworkEv: 'onDidPresent' },
|
||||
{ componentEv: `${name}-will-dismiss`, frameworkEv: 'onWillDismiss' },
|
||||
{ componentEv: `${name}-did-dismiss`, frameworkEv: 'onDidDismiss' },
|
||||
];
|
||||
|
||||
const Container = defineComponent<Props & OverlayProps>((props, { slots, emit }) => {
|
||||
const instance = getCurrentInstance();
|
||||
const adjustedEventListeners = needsKebabCase(instance.appContext.app.version) ? kebabCaseListeners : lowerCaseListeners;
|
||||
|
||||
const overlay = ref();
|
||||
const onVnodeMounted = async () => {
|
||||
const isOpen = props.isOpen;
|
||||
@ -76,7 +93,7 @@ export const defineOverlayContainer = <Props extends object>(name: string, compo
|
||||
|
||||
overlay.value = await overlay.value;
|
||||
|
||||
eventListeners.forEach(eventListener => {
|
||||
adjustedEventListeners.forEach(eventListener => {
|
||||
overlay.value.addEventListener(eventListener.componentEv, () => {
|
||||
emit(eventListener.frameworkEv);
|
||||
});
|
||||
@ -101,7 +118,7 @@ export const defineOverlayContainer = <Props extends object>(name: string, compo
|
||||
|
||||
Container.displayName = name;
|
||||
Container.props = [...componentProps, 'isOpen'];
|
||||
Container.emits = eventListeners.map(ev => ev.frameworkEv);
|
||||
Container.emits = [...lowerCaseListeners.map(ev => ev.frameworkEv), ...kebabCaseListeners.map(ev => ev.frameworkEv)];
|
||||
|
||||
return Container;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons>
|
||||
<ion-button @click="dismiss">Dismiss</ion-button>
|
||||
<ion-button @click="dismiss" id="dismiss">Dismiss</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Modal</ion-title>
|
||||
</ion-toolbar>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<ion-page>
|
||||
<ion-page data-pageid="overlays">
|
||||
<ion-header :translucent="true">
|
||||
<ion-toolbar>
|
||||
<ion-buttons>
|
||||
@ -66,6 +66,13 @@
|
||||
|
||||
<ion-button @click="changeLoadingProps()" id="change-loading-props">Quickly Change Loading Props</ion-button>
|
||||
|
||||
<br /><br />
|
||||
|
||||
Modal onWillPresent: <div id="willPresent">{{ willPresent }}</div><br />
|
||||
Modal onDidPresent: <div id="didPresent">{{ didPresent }}</div><br />
|
||||
Modal onWillDismiss: <div id="willDismiss">{{ willDismiss }}</div><br />
|
||||
Modal onDidDismiss: <div id="didDismiss">{{ didDismiss }}</div><br />
|
||||
|
||||
<ion-action-sheet
|
||||
:is-open="isActionSheetOpen"
|
||||
:buttons="actionSheetButtons"
|
||||
@ -93,7 +100,10 @@
|
||||
<ion-modal
|
||||
:is-open="isModalOpen"
|
||||
:componentProps="overlayProps"
|
||||
@onDidDismiss="setModalRef(false)"
|
||||
@onWillPresent="onModalWillPresent"
|
||||
@onDidPresent="onModalDidPresent"
|
||||
@onWillDismiss="onModalWillDismiss"
|
||||
@onDidDismiss="onModalDidDismiss"
|
||||
>
|
||||
<ModalContent></ModalContent>
|
||||
</ion-modal>
|
||||
@ -326,7 +336,25 @@ export default defineComponent({
|
||||
}, 10);
|
||||
}
|
||||
|
||||
const willPresent = ref(0);
|
||||
const didPresent = ref(0);
|
||||
const willDismiss = ref(0);
|
||||
const didDismiss = ref(0);
|
||||
|
||||
const onModalWillPresent = () => willPresent.value += 1;
|
||||
const onModalDidPresent = () => { didPresent.value += 1; setModalRef(true); }
|
||||
const onModalWillDismiss = () => willDismiss.value += 1;
|
||||
const onModalDidDismiss = () => { didDismiss.value += 1; setModalRef(false); }
|
||||
|
||||
return {
|
||||
onModalWillPresent,
|
||||
onModalDidPresent,
|
||||
onModalWillDismiss,
|
||||
onModalDidDismiss,
|
||||
willPresent,
|
||||
didPresent,
|
||||
willDismiss,
|
||||
didDismiss,
|
||||
changeLoadingProps,
|
||||
overlayProps,
|
||||
present,
|
||||
|
@ -1,5 +1,6 @@
|
||||
describe('Overlays', () => {
|
||||
beforeEach(() => {
|
||||
cy.viewport(1000, 900);
|
||||
cy.visit('http://localhost:8080/overlays')
|
||||
})
|
||||
|
||||
@ -7,7 +8,6 @@ describe('Overlays', () => {
|
||||
|
||||
for (let overlay of overlays) {
|
||||
it(`should open and close ${overlay} via controller`, () => {
|
||||
console.log(overlay)
|
||||
cy.get(`ion-radio#${overlay}`).click();
|
||||
cy.get('ion-radio#controller').click();
|
||||
|
||||
@ -34,7 +34,6 @@ describe('Overlays', () => {
|
||||
|
||||
for (let overlay of overlays) {
|
||||
it(`should open and close ${overlay} via component`, () => {
|
||||
console.log(overlay)
|
||||
cy.get(`ion-radio#${overlay}`).click();
|
||||
cy.get('ion-radio#component').click();
|
||||
|
||||
@ -104,4 +103,55 @@ describe('Overlays', () => {
|
||||
|
||||
cy.get('ion-loading').should('have.length', 1);
|
||||
});
|
||||
|
||||
it('should fire lifecycle events on overlays', () => {
|
||||
cy.get('ion-radio#ion-modal').click();
|
||||
cy.get('ion-radio#component').click();
|
||||
|
||||
cy.get('ion-button#present-overlay').click();
|
||||
cy.get('ion-modal').should('exist');
|
||||
|
||||
testLifecycle('overlays', {
|
||||
willPresent: 1,
|
||||
didPresent: 1,
|
||||
willDismiss: 0,
|
||||
didDismiss: 0
|
||||
});
|
||||
|
||||
cy.get('ion-modal #dismiss').click();
|
||||
|
||||
testLifecycle('overlays', {
|
||||
willPresent: 1,
|
||||
didPresent: 1,
|
||||
willDismiss: 1,
|
||||
didDismiss: 1
|
||||
});
|
||||
|
||||
cy.get('ion-button#present-overlay').click();
|
||||
cy.get('ion-modal').should('exist');
|
||||
|
||||
testLifecycle('overlays', {
|
||||
willPresent: 2,
|
||||
didPresent: 2,
|
||||
willDismiss: 1,
|
||||
didDismiss: 1
|
||||
});
|
||||
|
||||
cy.get('ion-modal #dismiss').click();
|
||||
|
||||
testLifecycle('overlays', {
|
||||
willPresent: 2,
|
||||
didPresent: 2,
|
||||
willDismiss: 2,
|
||||
didDismiss: 2
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
const testLifecycle = (selector, expected = {}) => {
|
||||
cy.get(`[data-pageid=${selector}] #willPresent`).should('have.text', expected.willPresent);
|
||||
cy.get(`[data-pageid=${selector}] #didPresent`).should('have.text', expected.didPresent);
|
||||
cy.get(`[data-pageid=${selector}] #willDismiss`).should('have.text', expected.willDismiss);
|
||||
cy.get(`[data-pageid=${selector}] #didDismiss`).should('have.text', expected.didDismiss);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user