Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 024d090

Browse files
authored
fix(vue): emit component-specific overlay events (#30688)
Issue number: resolves #30641 --------- <!-- 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? <!-- Please describe the current behavior that you are modifying. --> Currently, Vue modals do not emit `ionModal...` events. This happened due to a change in the way the stencil output targets for Vue changed. Christian [updated the overlays](https://github.com/ionic-team/ionic-framework/pull/30227/files#diff-7e46aba01094c4917cd55e8eebd263fc4a297a2d62143f1ae30959ec4e023b6f) to support the base events, but not the component-specific events. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> With this change, you'll be able to bind to the events as described in the Ionic documentation. ## 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 Current dev build: ``` 8.7.5-dev.11758311583.14f4e9d9 ```
1 parent 36c56e7 commit 024d090

File tree

3 files changed

+201
-8
lines changed

3 files changed

+201
-8
lines changed

‎packages/vue/src/utils/overlays.ts‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { VNode,ComponentOptions } from "vue";
2-
import { defineComponent, h, ref,onMounted } from "vue";
1+
import type { ComponentOptions,VNode } from "vue";
2+
import { defineComponent, h, onMounted,ref } from "vue";
33

44
// TODO(FW-2969): types
55

@@ -147,23 +147,32 @@ export const defineOverlayContainer = <Props extends object>(
147147
const elementRef = ref();
148148

149149
onMounted(() => {
150+
// Convert name from kebab-case to camelCase
151+
const componentName = name.replace(/-([a-z])/g, (_, letter) =>
152+
letter.toUpperCase()
153+
);
150154
elementRef.value.addEventListener("ionMount", (ev: Event) => {
151155
emit("ionMount", ev);
156+
emit(componentName + "IonMount", ev);
152157
isOpen.value = true;
153158
});
154159
elementRef.value.addEventListener("willPresent", (ev: Event) => {
155160
emit("willPresent", ev);
161+
emit(componentName + "WillPresent", ev);
156162
isOpen.value = true;
157163
});
158164
elementRef.value.addEventListener("didDismiss", (ev: Event) => {
159165
emit("didDismiss", ev);
166+
emit(componentName + "DidDismiss", ev);
160167
isOpen.value = false;
161168
});
162169
elementRef.value.addEventListener("willDismiss", (ev: Event) => {
163170
emit("willDismiss", ev);
171+
emit(componentName + "WillDismiss", ev);
164172
});
165173
elementRef.value.addEventListener("didPresent", (ev: Event) => {
166174
emit("didPresent", ev);
175+
emit(componentName + "DidPresent", ev);
167176
});
168177
});
169178

‎packages/vue/test/base/src/views/Overlays.vue‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@
6464
Modal onDidPresent: <div id="didPresent">{{ didPresent }}</div><br />
6565
Modal onWillDismiss: <div id="willDismiss">{{ willDismiss }}</div><br />
6666
Modal onDidDismiss: <div id="didDismiss">{{ didDismiss }}</div><br />
67+
Modal ionModalWillPresent: <div id="ionModalWillPresent">{{ ionModalWillPresent }}</div><br />
68+
Modal ionModalDidPresent: <div id="ionModalDidPresent">{{ ionModalDidPresent }}</div><br />
69+
Modal ionModalWillDismiss: <div id="ionModalWillDismiss">{{ ionModalWillDismiss }}</div><br />
70+
Modal ionModalDidDismiss: <div id="ionModalDidDismiss">{{ ionModalDidDismiss }}</div><br />
6771
</div>
6872

6973
<ion-action-sheet
@@ -98,6 +102,10 @@
98102
@didPresent="onModalDidPresent"
99103
@willDismiss="onModalWillDismiss"
100104
@didDismiss="onModalDidDismiss"
105+
@ionModalWillPresent="onIonModalWillPresent"
106+
@ionModalDidPresent="onIonModalDidPresent"
107+
@ionModalWillDismiss="onIonModalWillDismiss"
108+
@ionModalDidDismiss="onIonModalDidDismiss"
101109
>
102110
<ModalContent :title="overlayProps.title"></ModalContent>
103111
</ion-modal>
@@ -266,6 +274,19 @@ export default defineComponent({
266274
267275
const openModal = async () => {
268276
const modal = await modalController.create({ cssClass: "ion-modal-controller", component: ModalContent, componentProps: overlayProps });
277+
278+
// Attach lifecycle listeners for controller-created modal
279+
modal.addEventListener('willPresent', () => { willPresent.value += 1; });
280+
modal.addEventListener('didPresent', () => { didPresent.value += 1; });
281+
modal.addEventListener('willDismiss', () => { willDismiss.value += 1; });
282+
modal.addEventListener('didDismiss', () => { didDismiss.value += 1; });
283+
284+
// Long-form event names
285+
modal.addEventListener('ionModalWillPresent', () => { ionModalWillPresent.value += 1; });
286+
modal.addEventListener('ionModalDidPresent', () => { ionModalDidPresent.value += 1; });
287+
modal.addEventListener('ionModalWillDismiss', () => { ionModalWillDismiss.value += 1; });
288+
modal.addEventListener('ionModalDidDismiss', () => { ionModalDidDismiss.value += 1; });
289+
269290
await modal.present();
270291
}
271292
@@ -335,21 +356,37 @@ export default defineComponent({
335356
const didPresent = ref(0);
336357
const willDismiss = ref(0);
337358
const didDismiss = ref(0);
359+
const ionModalWillPresent = ref(0);
360+
const ionModalDidPresent = ref(0);
361+
const ionModalWillDismiss = ref(0);
362+
const ionModalDidDismiss = ref(0);
338363
339364
const onModalWillPresent = () => willPresent.value += 1;
340365
const onModalDidPresent = () => { didPresent.value += 1; setModalRef(true); }
341366
const onModalWillDismiss = () => willDismiss.value += 1;
342367
const onModalDidDismiss = () => { didDismiss.value += 1; setModalRef(false); }
368+
const onIonModalWillPresent = () => ionModalWillPresent.value += 1;
369+
const onIonModalDidPresent = () => ionModalDidPresent.value += 1;
370+
const onIonModalWillDismiss = () => ionModalWillDismiss.value += 1;
371+
const onIonModalDidDismiss = () => ionModalDidDismiss.value += 1;
343372
344373
return {
345374
onModalWillPresent,
346375
onModalDidPresent,
347376
onModalWillDismiss,
348377
onModalDidDismiss,
378+
onIonModalWillPresent,
379+
onIonModalDidPresent,
380+
onIonModalWillDismiss,
381+
onIonModalDidDismiss,
349382
willPresent,
350383
didPresent,
351384
willDismiss,
352385
didDismiss,
386+
ionModalWillPresent,
387+
ionModalDidPresent,
388+
ionModalWillDismiss,
389+
ionModalDidDismiss,
353390
changeLoadingProps,
354391
overlayProps,
355392
present,

‎packages/vue/test/base/tests/e2e/specs/overlays.cy.js‎

Lines changed: 153 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
const testController = (overlay, shadow = false) => {
22
const selector = `.${overlay}-controller`;
3-
cy.get(`ion-radio#${overlay}`).click();
4-
cy.get('ion-radio#controller').click();
3+
cy.get(`ion-radio#${overlay}`)
4+
.scrollIntoView({ offset: { top: -100, left: 0 } })
5+
.click({ force: true });
6+
cy.get('ion-radio#controller')
7+
.scrollIntoView({ offset: { top: -100, left: 0 } })
8+
.click({ force: true });
59

610
cy.get('ion-button#present-overlay').click();
711
cy.get(selector).should('exist').should('be.visible');
@@ -16,8 +20,12 @@ const testController = (overlay, shadow = false) => {
1620
}
1721

1822
const testComponent = (overlay, shadow = false) => {
19-
cy.get(`ion-radio#${overlay}`).click();
20-
cy.get('ion-radio#component').click();
23+
cy.get(`ion-radio#${overlay}`)
24+
.scrollIntoView({ offset: { top: -100, left: 0 } })
25+
.click({ force: true });
26+
cy.get('ion-radio#component')
27+
.scrollIntoView({ offset: { top: -100, left: 0 } })
28+
.click({ force: true });
2129

2230
cy.get('ion-button#present-overlay').click();
2331
cy.get(overlay).should('exist').should('be.visible');
@@ -40,8 +48,12 @@ const testComponent = (overlay, shadow = false) => {
4048
}
4149

4250
const testInlineOverlay = (overlay, shadow = false) => {
43-
cy.get(`ion-radio#${overlay}`).click();
44-
cy.get('ion-radio#component').click();
51+
cy.get(`ion-radio#${overlay}`)
52+
.scrollIntoView({ offset: { top: -100, left: 0 } })
53+
.click({ force: true });
54+
cy.get('ion-radio#component')
55+
.scrollIntoView({ offset: { top: -100, left: 0 } })
56+
.click({ force: true });
4557

4658
cy.get('ion-button#present-overlay').click();
4759
cy.get(overlay).should('exist').should('be.visible');
@@ -214,6 +226,135 @@ describe('Overlays', () => {
214226
});
215227
});
216228

229+
it('should fire long-form lifecycle events on overlays', () => {
230+
cy.get('ion-radio#ion-modal').click();
231+
cy.get('ion-radio#component').click();
232+
233+
cy.get('ion-button#present-overlay').click();
234+
cy.get('ion-modal').should('exist');
235+
236+
testLongLifecycle('overlays', {
237+
willPresent: 1,
238+
didPresent: 1,
239+
willDismiss: 0,
240+
didDismiss: 0
241+
});
242+
243+
cy.get('ion-modal #dismiss').click();
244+
245+
testLongLifecycle('overlays', {
246+
willPresent: 1,
247+
didPresent: 1,
248+
willDismiss: 1,
249+
didDismiss: 1
250+
});
251+
252+
cy.get('ion-button#present-overlay').click();
253+
cy.get('ion-modal').should('exist');
254+
255+
testLongLifecycle('overlays', {
256+
willPresent: 2,
257+
didPresent: 2,
258+
willDismiss: 1,
259+
didDismiss: 1
260+
});
261+
262+
cy.get('ion-modal #dismiss').click();
263+
264+
testLongLifecycle('overlays', {
265+
willPresent: 2,
266+
didPresent: 2,
267+
willDismiss: 2,
268+
didDismiss: 2
269+
});
270+
});
271+
272+
it('should fire lifecycle events on controller overlays', () => {
273+
cy.get('ion-radio#ion-modal').click();
274+
cy.get('ion-radio#controller').click();
275+
276+
cy.get('ion-button#present-overlay').click();
277+
cy.get('ion-modal').should('exist');
278+
279+
testLifecycle('overlays', {
280+
willPresent: 1,
281+
didPresent: 1,
282+
willDismiss: 0,
283+
didDismiss: 0
284+
});
285+
286+
cy.get('ion-modal #dismiss').click();
287+
288+
testLifecycle('overlays', {
289+
willPresent: 1,
290+
didPresent: 1,
291+
willDismiss: 1,
292+
didDismiss: 1
293+
});
294+
295+
cy.get('ion-button#present-overlay').click();
296+
cy.get('ion-modal').should('exist');
297+
298+
testLifecycle('overlays', {
299+
willPresent: 2,
300+
didPresent: 2,
301+
willDismiss: 1,
302+
didDismiss: 1
303+
});
304+
305+
cy.get('ion-modal #dismiss').click();
306+
307+
testLifecycle('overlays', {
308+
willPresent: 2,
309+
didPresent: 2,
310+
willDismiss: 2,
311+
didDismiss: 2
312+
});
313+
});
314+
315+
it('should fire long-form lifecycle events on controller overlays', () => {
316+
cy.get('ion-radio#ion-modal').click();
317+
cy.get('ion-radio#controller').click();
318+
319+
cy.get('ion-button#present-overlay').click();
320+
cy.get('ion-modal').should('exist');
321+
322+
testLongLifecycle('overlays', {
323+
willPresent: 1,
324+
didPresent: 1,
325+
willDismiss: 0,
326+
didDismiss: 0
327+
});
328+
329+
cy.get('ion-modal #dismiss').click();
330+
331+
testLongLifecycle('overlays', {
332+
willPresent: 1,
333+
didPresent: 1,
334+
willDismiss: 1,
335+
didDismiss: 1
336+
});
337+
338+
cy.get('ion-button#present-overlay').click();
339+
cy.get('ion-modal').should('exist');
340+
341+
testLongLifecycle('overlays', {
342+
willPresent: 2,
343+
didPresent: 2,
344+
willDismiss: 1,
345+
didDismiss: 1
346+
});
347+
348+
cy.get('ion-modal #dismiss').click();
349+
350+
testLongLifecycle('overlays', {
351+
willPresent: 2,
352+
didPresent: 2,
353+
willDismiss: 2,
354+
didDismiss: 2
355+
});
356+
});
357+
217358
it('should unmount modal via component', () => {
218359
cy.get('ion-radio#ion-modal').click();
219360
cy.get('ion-radio#component').click();
@@ -260,3 +401,9 @@ const testLifecycle = (selector, expected = {}) => {
260401
cy.get(`[data-pageid=${selector}] #didDismiss`).should('have.text', expected.didDismiss);
261402
}
262403

404+
const testLongLifecycle = (selector, expected = {}) => {
405+
cy.get(`[data-pageid=${selector}] #ionModalWillPresent`).should('have.text', expected.willPresent);
406+
cy.get(`[data-pageid=${selector}] #ionModalDidPresent`).should('have.text', expected.didPresent);
407+
cy.get(`[data-pageid=${selector}] #ionModalWillDismiss`).should('have.text', expected.willDismiss);
408+
cy.get(`[data-pageid=${selector}] #ionModalDidDismiss`).should('have.text', expected.didDismiss);
409+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /