Skip to content

Commit 1b1b1a3

Browse files
authored
fix(datetime): typing in time now updates value (#25561)
resolves #25560
1 parent 3b0ed78 commit 1b1b1a3

File tree

5 files changed

+108
-4
lines changed

5 files changed

+108
-4
lines changed

core/src/components.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,10 @@ export namespace Components {
18621862
*/
18631863
"numericInput": boolean;
18641864
"scrollActiveItemIntoView": () => Promise<void>;
1865+
/**
1866+
* Sets the value prop and fires the ionChange event. This is used when we need to fire ionChange from user-generated events that cannot be caught with normal input/change event listeners.
1867+
*/
1868+
"setValue": (value?: string | number | undefined) => Promise<void>;
18651869
/**
18661870
* The selected option in the picker.
18671871
*/

core/src/components/picker-column-internal/picker-column-internal.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,15 @@ export class PickerColumnInternal implements ComponentInterface {
144144
}
145145
}
146146

147-
private setValue(value?: string | number) {
147+
/**
148+
* Sets the value prop and fires the ionChange event.
149+
* This is used when we need to fire ionChange from
150+
* user-generated events that cannot be caught with normal
151+
* input/change event listeners.
152+
* @internal
153+
*/
154+
@Method()
155+
async setValue(value?: string | number) {
148156
const { items } = this;
149157
this.value = value;
150158
const findItem = items.find((item) => item.value === value);

core/src/components/picker-internal/picker-internal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ export class PickerInternal implements ComponentInterface {
347347
*/
348348
const findItemFromCompleteValue = values.find(({ text }) => text.replace(/^0+/, '') === inputEl.value);
349349
if (findItemFromCompleteValue) {
350-
inputModeColumn.value = findItemFromCompleteValue.value;
350+
inputModeColumn.setValue(findItemFromCompleteValue.value);
351351
return;
352352
}
353353

@@ -377,7 +377,7 @@ export class PickerInternal implements ComponentInterface {
377377
const item = colEl.items.find(({ text }) => text.replace(behavior, '') === value);
378378

379379
if (item) {
380-
colEl.value = item.value;
380+
colEl.setValue(item.value);
381381
}
382382
};
383383

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { expect } from '@playwright/test';
2+
import { test } from '@utils/test/playwright';
3+
import type { E2ELocator } from '@utils/test/playwright/page/utils/locator';
4+
5+
test.describe('picker-internal: keyboard entry', () => {
6+
test('should scroll to and update the value prop for a single column', async ({ page }) => {
7+
await page.setContent(`
8+
<ion-picker-internal>
9+
<ion-picker-column-internal></ion-picker-column-internal>
10+
</ion-picker-internal>
11+
12+
<script>
13+
const column = document.querySelector('ion-picker-column-internal');
14+
column.items = [
15+
{ text: '01', value: 1 },
16+
{ text: '02', value: 2 },
17+
{ text: '03', value: 3 },
18+
{ text: '04', value: 4 },
19+
{ text: '05', value: 5 }
20+
];
21+
column.value = 5;
22+
column.numericInput = true;
23+
</script>
24+
`);
25+
26+
const column = page.locator('ion-picker-column-internal');
27+
const ionChange = await page.spyOnEvent('ionChange');
28+
await column.focus();
29+
30+
await page.keyboard.press('Digit2');
31+
32+
await expect(ionChange).toHaveReceivedEventDetail({ text: '02', value: 2 });
33+
await expect(column).toHaveJSProperty('value', 2);
34+
});
35+
36+
test('should scroll to and update the value prop for multiple columns', async ({ page }) => {
37+
await page.setContent(`
38+
<ion-picker-internal>
39+
<ion-picker-column-internal id="first"></ion-picker-column-internal>
40+
<ion-picker-column-internal id="second"></ion-picker-column-internal>
41+
</ion-picker-internal>
42+
43+
<script>
44+
const firstColumn = document.querySelector('ion-picker-column-internal#first');
45+
firstColumn.items = [
46+
{ text: '01', value: 1 },
47+
{ text: '02', value: 2 },
48+
{ text: '03', value: 3 },
49+
{ text: '04', value: 4 },
50+
{ text: '05', value: 5 }
51+
];
52+
firstColumn.value = 5;
53+
firstColumn.numericInput = true;
54+
55+
const secondColumn = document.querySelector('ion-picker-column-internal#second');
56+
secondColumn.items = [
57+
{ text: '20', value: 20 },
58+
{ text: '21', value: 21 },
59+
{ text: '22', value: 22 },
60+
{ text: '23', value: 23 },
61+
{ text: '24', value: 24 }
62+
];
63+
secondColumn.value = 22;
64+
secondColumn.numericInput = true;
65+
</script>
66+
`);
67+
68+
const firstColumn = page.locator('ion-picker-column-internal#first');
69+
const secondColumn = page.locator('ion-picker-column-internal#second');
70+
const highlight = page.locator('ion-picker-internal .picker-highlight');
71+
const firstIonChange = await (firstColumn as E2ELocator).spyOnEvent('ionChange');
72+
const secondIonChange = await (secondColumn as E2ELocator).spyOnEvent('ionChange');
73+
74+
const box = await highlight.boundingBox();
75+
if (box !== null) {
76+
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
77+
}
78+
79+
await expect(firstColumn).toHaveClass(/picker-column-active/);
80+
await expect(secondColumn).toHaveClass(/picker-column-active/);
81+
82+
await page.keyboard.press('Digit2');
83+
84+
await expect(firstIonChange).toHaveReceivedEventDetail({ text: '02', value: 2 });
85+
await expect(firstColumn).toHaveJSProperty('value', 2);
86+
87+
await page.keyboard.press('Digit2+Digit4');
88+
89+
await expect(secondIonChange).toHaveReceivedEventDetail({ text: '24', value: 24 });
90+
await expect(secondColumn).toHaveJSProperty('value', 24);
91+
});
92+
});

core/src/utils/test/playwright/page/utils/locator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export interface E2ELocator extends Locator {
2121
* ...
2222
* await ionChange.next();
2323
*/
24-
spyOnEvent: (eventName: string) => void;
24+
spyOnEvent: (eventName: string) => Promise<EventSpy>;
2525
}
2626

2727
export const locator = (

0 commit comments

Comments
 (0)