Skip to content

Commit 11554a5

Browse files
fix(vue): update output target and properly emit events (#30227)
Issue number: resolves #30206 resolves #30178 resolves #30177 resolves #30175 resolves #30170 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? There have been plenty of issues reported in regards to Vue components failing to propagate events. It seems like when we updated the Vue output target and started to use the provided runtime code from the output target, we have changed the way how event names are computed. Ionic has used a custom wrapper for handling events that would kebab case event names. That is no longer needed and removing it fixes observed issues. Reproduction case working: https://stackblitz.com/edit/vj18czas-wdhzxjom?file=package.json ## What is the new behavior? We have received a fix for this in stenciljs/output-targets#617 which I hope will resolve this issue by updating the dependency. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer for more information. --> ## Other information Dev build: `8.4.4-dev.11741193800.14916f6f`
1 parent ba8d8f4 commit 11554a5

File tree

9 files changed

+43
-102
lines changed

9 files changed

+43
-102
lines changed

core/package-lock.json

+8-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"@stencil/angular-output-target": "^0.10.0",
5151
"@stencil/react-output-target": "0.5.3",
5252
"@stencil/sass": "^3.0.9",
53-
"@stencil/vue-output-target": "^0.9.0",
53+
"@stencil/vue-output-target": "^0.9.6",
5454
"@types/jest": "^29.5.6",
5555
"@types/node": "^14.6.0",
5656
"@typescript-eslint/eslint-plugin": "^6.7.2",

core/src/global/ionic-global.ts

+1-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getMode, setMode, setPlatformHelpers } from '@stencil/core';
1+
import { getMode, setMode } from '@stencil/core';
22

33
import type { IonicConfig, Mode } from '../interface';
44
import { isPlatform, setupPlatforms } from '../utils/platform';
@@ -22,18 +22,6 @@ export const initialize = (userConfig: IonicConfig = {}) => {
2222
const win = window;
2323
const Ionic = ((win as any).Ionic = (win as any).Ionic || {});
2424

25-
const platformHelpers: any = {};
26-
if (userConfig._ael) {
27-
platformHelpers.ael = userConfig._ael;
28-
}
29-
if (userConfig._rel) {
30-
platformHelpers.rel = userConfig._rel;
31-
}
32-
if (userConfig._ce) {
33-
platformHelpers.ce = userConfig._ce;
34-
}
35-
setPlatformHelpers(platformHelpers);
36-
3725
// create the Ionic.config from raw config object (if it exists)
3826
// and convert Ionic.config into a ConfigApi that has a get() fn
3927
const configObj = {

core/src/utils/config.ts

-3
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,6 @@ export interface IonicConfig {
234234
_forceStatusbarPadding?: boolean;
235235
_testing?: boolean;
236236
_zoneGate?: (h: () => any) => any;
237-
_ael?: (el: any, name: string, cb: any, opts: any) => any;
238-
_rel?: (el: any, name: string, cb: any, opts: any) => any;
239-
_ce?: (eventName: string, opts: any) => any;
240237
}
241238

242239
type FocusManagerPriority = 'content' | 'heading' | 'banner';

core/src/utils/helpers.ts

+1-27
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const transitionEnd = (el: HTMLElement | null, expectedDuration = 0, callback: (
4242
if (el) {
4343
el.addEventListener('webkitTransitionEnd', onTransitionEnd, opts);
4444
el.addEventListener('transitionend', onTransitionEnd, opts);
45-
animationTimeout = setTimeout(onTransitionEnd, expectedDuration + ANIMATION_FALLBACK_TIMEOUT);
45+
animationTimeout = setTimeout(onTransitionEnd, expectedDuration + ANIMATION_FALLBACK_TIMEOUT) as unknown as number;
4646

4747
unRegTrans = () => {
4848
if (animationTimeout !== undefined) {
@@ -190,36 +190,10 @@ export const inheritAriaAttributes = (el: HTMLElement, ignoreList?: string[]) =>
190190
};
191191

192192
export const addEventListener = (el: any, eventName: string, callback: any, opts?: any) => {
193-
if (typeof (window as any) !== 'undefined') {
194-
const win = window as any;
195-
const config = win?.Ionic?.config;
196-
if (config) {
197-
const ael = config.get('_ael');
198-
if (ael) {
199-
return ael(el, eventName, callback, opts);
200-
} else if (config._ael) {
201-
return config._ael(el, eventName, callback, opts);
202-
}
203-
}
204-
}
205-
206193
return el.addEventListener(eventName, callback, opts);
207194
};
208195

209196
export const removeEventListener = (el: any, eventName: string, callback: any, opts?: any) => {
210-
if (typeof (window as any) !== 'undefined') {
211-
const win = window as any;
212-
const config = win?.Ionic?.config;
213-
if (config) {
214-
const rel = config.get('_rel');
215-
if (rel) {
216-
return rel(el, eventName, callback, opts);
217-
} else if (config._rel) {
218-
return config._rel(el, eventName, callback, opts);
219-
}
220-
}
221-
}
222-
223197
return el.removeEventListener(eventName, callback, opts);
224198
};
225199

packages/vue/package-lock.json

+7-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/vue/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"@ionic/prettier-config": "^2.0.0",
5555
"@rollup/plugin-node-resolve": "^16.0.0",
5656
"@rollup/plugin-typescript": "^11.1.5",
57-
"@stencil/vue-output-target": "0.9.4",
57+
"@stencil/vue-output-target": "0.9.6",
5858
"@typescript-eslint/eslint-plugin": "^5.48.2",
5959
"@typescript-eslint/parser": "^5.48.2",
6060
"change-case": "^4.1.1",

packages/vue/src/ionic-vue.ts

+1-26
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,6 @@ import type { IonicConfig } from "@ionic/core/components";
22
import { initialize } from "@ionic/core/components";
33
import type { App, Plugin } from "vue";
44

5-
// TODO(FW-2969): types
6-
7-
const toKebabCase = (eventName: string) => {
8-
return eventName
9-
.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2")
10-
.toLowerCase();
11-
};
12-
13-
const getHelperFunctions = () => {
14-
return {
15-
ael: (el: any, eventName: string, cb: any, opts: any) =>
16-
el.addEventListener(toKebabCase(eventName), cb, opts),
17-
rel: (el: any, eventName: string, cb: any, opts: any) =>
18-
el.removeEventListener(toKebabCase(eventName), cb, opts),
19-
ce: (eventName: string, opts: any) =>
20-
new CustomEvent(toKebabCase(eventName), opts),
21-
};
22-
};
23-
245
export const IonicVue: Plugin<[IonicConfig?]> = {
256
async install(_: App, config: IonicConfig = {}) {
267
/**
@@ -34,12 +15,6 @@ export const IonicVue: Plugin<[IonicConfig?]> = {
3415
document.documentElement.classList.add("ion-ce");
3516
}
3617

37-
const { ael, rel, ce } = getHelperFunctions();
38-
initialize({
39-
...config,
40-
_ael: ael,
41-
_rel: rel,
42-
_ce: ce,
43-
});
18+
initialize(config);
4419
},
4520
};

packages/vue/src/utils/overlays.ts

+23-17
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ export const defineOverlayContainer = <Props extends object>(
2020
const createControllerComponent = (options: ComponentOptions) => {
2121
return defineComponent<Props & OverlayProps>((props, { slots, emit }) => {
2222
const eventListeners = [
23-
{ componentEv: `${name}-will-present`, frameworkEv: "willPresent" },
24-
{ componentEv: `${name}-did-present`, frameworkEv: "didPresent" },
25-
{ componentEv: `${name}-will-dismiss`, frameworkEv: "willDismiss" },
26-
{ componentEv: `${name}-did-dismiss`, frameworkEv: "didDismiss" },
23+
{ componentEv: `${name}WillPresent`, frameworkEv: "willPresent" },
24+
{ componentEv: `${name}DidPresent`, frameworkEv: "didPresent" },
25+
{ componentEv: `${name}WillDismiss`, frameworkEv: "willDismiss" },
26+
{ componentEv: `${name}DidDismiss`, frameworkEv: "didDismiss" },
2727
];
2828

2929
if (defineCustomElement !== undefined) {
@@ -139,26 +139,32 @@ export const defineOverlayContainer = <Props extends object>(
139139
}, options);
140140
};
141141
const createInlineComponent = (options: any) => {
142-
return defineComponent((props, { slots }) => {
142+
return defineComponent((props, { slots, emit }) => {
143143
if (defineCustomElement !== undefined) {
144144
defineCustomElement();
145145
}
146146
const isOpen = ref(false);
147147
const elementRef = ref();
148148

149149
onMounted(() => {
150-
elementRef.value.addEventListener(
151-
"ion-mount",
152-
() => (isOpen.value = true)
153-
);
154-
elementRef.value.addEventListener(
155-
"will-present",
156-
() => (isOpen.value = true)
157-
);
158-
elementRef.value.addEventListener(
159-
"did-dismiss",
160-
() => (isOpen.value = false)
161-
);
150+
elementRef.value.addEventListener("ionMount", (ev: Event) => {
151+
emit("ionMount", ev);
152+
isOpen.value = true;
153+
});
154+
elementRef.value.addEventListener("willPresent", (ev: Event) => {
155+
emit("willPresent", ev);
156+
isOpen.value = true;
157+
});
158+
elementRef.value.addEventListener("didDismiss", (ev: Event) => {
159+
emit("didDismiss", ev);
160+
isOpen.value = false;
161+
});
162+
elementRef.value.addEventListener("willDismiss", (ev: Event) => {
163+
emit("willDismiss", ev);
164+
});
165+
elementRef.value.addEventListener("didPresent", (ev: Event) => {
166+
emit("didPresent", ev);
167+
});
162168
});
163169

164170
return () => {

0 commit comments

Comments
 (0)