From aacb58a3224e3cc51c731d0c9aa52f52c9276692 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Mon, 28 Feb 2022 13:51:52 -0500 Subject: [PATCH] fix(datetime): persist minutes column on hour change (#24829) Resolves #24821 --- .../picker-column-internal.tsx | 36 ++++++++-- .../picker-column-internal/test/basic/e2e.ts | 56 +++++++++++++++ .../test/basic/index.html | 69 +++++++++++++++++++ 3 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 core/src/components/picker-column-internal/test/basic/e2e.ts create mode 100644 core/src/components/picker-column-internal/test/basic/index.html diff --git a/core/src/components/picker-column-internal/picker-column-internal.tsx b/core/src/components/picker-column-internal/picker-column-internal.tsx index fd4c0f7235..f870f6c0c0 100644 --- a/core/src/components/picker-column-internal/picker-column-internal.tsx +++ b/core/src/components/picker-column-internal/picker-column-internal.tsx @@ -118,6 +118,25 @@ export class PickerColumnInternal implements ComponentInterface { } } + componentDidRender() { + const { activeItem, items, isColumnVisible, value } = this; + + if (isColumnVisible) { + if (activeItem) { + this.scrollActiveItemIntoView(); + } else if (items[0]?.value !== value) { + /** + * If the picker column does not have an active item and the current value + * does not match the first item in the picker column, that means + * the value is out of bounds. In this case, we assign the value to the + * first item to match the scroll position of the column. + * + */ + this.value = items[0].value; + } + } + } + /** @internal */ @Method() async scrollActiveItemIntoView() { @@ -129,12 +148,19 @@ export class PickerColumnInternal implements ComponentInterface { } private centerPickerItemInView = (target: HTMLElement, smooth = true) => { - this.el.scroll({ + const { el, isColumnVisible } = this; + if (isColumnVisible) { // (Vertical offset from parent) - (three empty picker rows) + (half the height of the target to ensure the scroll triggers) - top: target.offsetTop - (3 * target.clientHeight) + (target.clientHeight / 2), - left: 0, - behavior: smooth ? 'smooth' : undefined - }); + const top = target.offsetTop - (3 * target.clientHeight) + (target.clientHeight / 2); + + if (el.scrollTop !== top) { + el.scroll({ + top, + left: 0, + behavior: smooth ? 'smooth' : undefined + }); + } + } } /** diff --git a/core/src/components/picker-column-internal/test/basic/e2e.ts b/core/src/components/picker-column-internal/test/basic/e2e.ts new file mode 100644 index 0000000000..c9bb72a84e --- /dev/null +++ b/core/src/components/picker-column-internal/test/basic/e2e.ts @@ -0,0 +1,56 @@ +import { E2EPage, newE2EPage } from '@stencil/core/testing'; + + +describe('picker-column-internal', () => { + + let page: E2EPage; + + describe('default', () => { + + beforeEach(async () => { + page = await newE2EPage({ + url: '/src/components/picker-column-internal/test/basic?ionic:_testing=true' + }); + }); + + it('should render a picker item for each item', async () => { + const columns = await page.findAll('ion-picker-column-internal >>> .picker-item:not(.picker-item-empty)'); + expect(columns.length).toEqual(24); + }); + + it('should render 6 empty picker items', async () => { + const columns = await page.findAll('ion-picker-column-internal >>> .picker-item-empty'); + expect(columns.length).toEqual(6); + }); + + it('should not have an active item when value is not set', async () => { + const activeColumn = await page.findAll('ion-picker-column-internal >>> .picker-item-active'); + expect(activeColumn.length).toEqual(0); + }); + + it('should have an active item when value is set', async () => { + await page.$eval('ion-picker-column-internal#default', (el: any) => { + el.value = '12'; + }); + await page.waitForChanges(); + + const activeColumn = await page.find('ion-picker-column-internal >>> .picker-item-active'); + + expect(activeColumn).not.toBeNull(); + }); + + it('scrolling should change the active item', async () => { + await page.$eval('ion-picker-column-internal#default', (el: any) => { + el.scrollTop = 801; + }); + + await page.waitForChanges(); + + const activeColumn = await page.find('ion-picker-column-internal >>> .picker-item-active'); + + expect(activeColumn.innerText).toEqual('23'); + }); + + }); + +}); diff --git a/core/src/components/picker-column-internal/test/basic/index.html b/core/src/components/picker-column-internal/test/basic/index.html new file mode 100644 index 0000000000..4e67495842 --- /dev/null +++ b/core/src/components/picker-column-internal/test/basic/index.html @@ -0,0 +1,69 @@ + + + + + + Picker Column Internal - Basic + + + + + + + + + + + + + Picker Column Internal - Basic + + + +
+
+

Default

+ + + +
+
+
+ +
+ + +