diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index c591972fd8d..e73cd55e0b8 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -1086,6 +1086,9 @@ export class Datetime implements ComponentInterface { connectedCallback() { this.clearFocusVisible = startFocusVisible(this.el).destroy; + this.loadTimeout = setTimeout(() => { + this.ensureReadyIfVisible(); + }, 100); } disconnectedCallback() { @@ -1093,9 +1096,7 @@ export class Datetime implements ComponentInterface { this.clearFocusVisible(); this.clearFocusVisible = undefined; } - if (this.loadTimeout) { - clearTimeout(this.loadTimeout); - } + this.loadTimeoutCleanup(); } /** @@ -1146,6 +1147,13 @@ export class Datetime implements ComponentInterface { }); }; + private loadTimeoutCleanup = () => { + if (this.loadTimeout) { + clearTimeout(this.loadTimeout); + this.loadTimeout = undefined; + } + }; + componentDidLoad() { const { el, intersectionTrackerRef } = this; @@ -1193,7 +1201,10 @@ export class Datetime implements ComponentInterface { * we still initialize listeners and mark the component as ready. * * We schedule this after everything has had a chance to run. + * + * We also clean up the load timeout to ensure that we don't have multiple timeouts running. */ + this.loadTimeoutCleanup(); this.loadTimeout = setTimeout(() => { this.ensureReadyIfVisible(); }, 100); diff --git a/core/src/components/datetime/test/basic/datetime.e2e.ts b/core/src/components/datetime/test/basic/datetime.e2e.ts index 6104d0014cf..bbc6033374f 100644 --- a/core/src/components/datetime/test/basic/datetime.e2e.ts +++ b/core/src/components/datetime/test/basic/datetime.e2e.ts @@ -349,6 +349,43 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => { }); }); +/** + * This behavior does not differ across + * modes/directions. + */ + +configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => { + test.describe(title('datetime: month picker selection'), () => { + test('datetime: month picker selection', async ({ page }) => { + await page.setContent( + ` + + `, + config + ); + + await page.locator('.datetime-ready').waitFor(); + + const nextMonthButton = page.locator('ion-datetime .calendar-next-prev ion-button').nth(1); + const monthYearButton = page.locator('ion-datetime .calendar-month-year'); + + await expect(monthYearButton).toHaveText(/May 2022/); + + await nextMonthButton.click(); + await expect(monthYearButton).toHaveText(/June 2022/); + + await nextMonthButton.click(); + await expect(monthYearButton).toHaveText(/July 2022/); + + await monthYearButton.click(); + await page.waitForChanges(); + + const selectedMonthOptions = page.locator('.month-column ion-picker-column-option.option-active'); + await expect(selectedMonthOptions).toHaveCount(1); + }); + }); +}); + /** * This behavior does not differ across * modes/directions. diff --git a/core/src/components/picker-column/picker-column.tsx b/core/src/components/picker-column/picker-column.tsx index 905ba8cf81e..53d6ca90d17 100644 --- a/core/src/components/picker-column/picker-column.tsx +++ b/core/src/components/picker-column/picker-column.tsx @@ -1,7 +1,7 @@ import type { ComponentInterface, EventEmitter } from '@stencil/core'; import { Component, Element, Event, Host, Method, Prop, State, Watch, h } from '@stencil/core'; import { doc } from '@utils/browser'; -import { getElementRoot, raf } from '@utils/helpers'; +import { raf } from '@utils/helpers'; import { hapticSelectionChanged, hapticSelectionEnd, hapticSelectionStart } from '@utils/native/haptic'; import { isPlatform } from '@utils/platform'; import { createColorClasses } from '@utils/theme'; @@ -122,9 +122,7 @@ export class PickerColumn implements ComponentInterface { * Because this initial call to scrollActiveItemIntoView has to fire before * the scroll listener is set up, we need to manage the active class manually. */ - const oldActive = getElementRoot(el).querySelector( - `.${PICKER_ITEM_ACTIVE_CLASS}` - ); + const oldActive = el.querySelector(`.${PICKER_ITEM_ACTIVE_CLASS}`); if (oldActive) { this.setPickerItemActiveState(oldActive, false); }