8000 fix(datetime): prefer wheel sets working value on confirmation (#28520) · ionic-team/ionic-framework@e886e3f · GitHub
[go: up one dir, main page]

Skip to content

Commit e886e3f

Browse files
fix(datetime): prefer wheel sets working value on confirmation (#28520)
Issue number: resolves #25839 --------- <!-- 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. --> Confirming the working day when a datetime using a wheel picker without an initial value will result in a value of `undefined` instead of the displayed working day the user sees. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - `preferWheel` uses the working value on confirmation ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> Dev-build: `7.5.7-dev.11701896424.13d40ac9` Co-authored-by: liamdebeasi <liamdebeasi@users.noreply.github.com>
1 parent 37290df commit e886e3f

File tree

4 files changed

+327
-26
lines changed

4 files changed

+327
-26
lines changed

core/src/components/datetime/datetime.tsx

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,15 +492,24 @@ export class Datetime implements ComponentInterface {
492492
*/
493493
@Method()
494494
async confirm(closeOverlay = false) {
495-
const { isCalendarPicker, activeParts } = this;
495+
const { isCalendarPicker, activeParts, preferWheel, workingParts } = this;
496496

497497
/**
498498
* We only update the value if the presentation is not a calendar picker.
499499
*/
500500
if (activeParts !== undefined || !isCalendarPicker) {
501501
const activePartsIsArray = Array.isArray(activeParts);
502502
if (activePartsIsArray && activeParts.length === 0) {
503-
this.setValue(undefined);
503+
if (preferWheel) {
504+
/**
505+
* If the datetime is using a wheel picker, but the
506+
* active parts are empty, then the user has confirmed the
507+
* initial value (working parts) presented to them.
508+
*/
509+
this.setValue(convertDataToISO(workingParts));
510+
} else {
511+
this.setValue(undefined);
512+
}
504513
} else {
505514
this.setValue(convertDataToISO(activeParts));
506515
}
@@ -1356,11 +1365,21 @@ export class Datetime implements ComponentInterface {
13561365
const dayValues = (this.parsedDayValues = convertToArrayOfNumbers(this.dayValues));
13571366

13581367
const todayParts = (this.todayParts = parseDate(getToday())!);
1359-
this.defaultParts = getClosestValidDate(todayParts, monthValues, dayValues, yearValues, hourValues, minuteValues);
13601368

13611369
this.processMinParts();
13621370
this.processMaxParts();
13631371

1372+
this.defaultParts = getClosestValidDate({
1373+
refParts: todayParts,
1374+
monthValues,
1375+
dayValues,
1376+
yearValues,
1377+
hourValues,
1378+
minuteValues,
1379+
minParts: this.minParts,
1380+
maxParts: this.maxParts,
1381+
});
1382+
13641383
this.processValue(this.value);
13651384

13661385
this.emitStyle();

core/src/components/datetime/test/manipulation.spec.ts

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
subtractDays,
1717
addDays,
1818
validateParts,
19+
getClosestValidDate,
1920
} from '../utils/manipulation';
2021

2122
describe('addDays()', () => {
@@ -558,3 +559,160 @@ describe('validateParts()', () => {
558559
).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 30 });
559560
});
560561
});
562+
563+
describe('getClosestValidDate()', () => {
564+
it('should match a date with only month/day/year', () => {
565+
// October 10, 2023
566+
const refParts = { month: 10, day: 10, year: 2023 };
567+
// April 10, 2021
568+
const minParts = { month: 4, day: 10, year: 2021 };
569+
// September 14, 2021
570+
const maxParts = { month: 9, day: 14, year: 2021 };
571+
572+
// September 4, 2021
573+
const expected = { month: 9, day: 4, year: 2021, dayOfWeek: undefined };
574+
575+
expect(
576+
getClosestValidDate({
577+
refParts,
578+
monthValues: [2, 3, 7, 9, 10],
579+
dayValues: [4, 15, 25],
580+
yearValues: [2020, 2021, 2023],
581+
maxParts,
582+
minParts,
583+
})
584+
).toEqual(expected);
585+
});
586+
587+
it('should match a date when the reference date is before the min', () => {
588+
// April 2, 2020 3:20 PM
589+
const refParts = { month: 4, day: 2, year: 2020, hour: 15, minute: 20 };
590+
// September 10, 2021 10:10 AM
591+
const minParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 10 };
592+
// September 14, 2021 10:11 AM
593+
const maxParts = { month: 9, day: 14, year: 2021, hour: 10, minute: 11 };
594+
595+
// September 11, 2021 11:15 AM
596+
const expected = {
597+
year: 2021,
598+
day: 11,
599+
month: 9,
600+
hour: 11,
601+
minute: 15,
602+
ampm: 'am',
603+
dayOfWeek: undefined,
604+
};
605+
606+
expect(
607+
getClosestValidDate({
608+
refParts,
609+
monthValues: [4, 9, 11],
610+
dayValues: [11, 12, 13, 14],
611+
yearValues: [2020, 2021, 2023],
612+
hourValues: [9, 10, 11],
613+
minuteValues: [11, 12, 13, 14, 15],
614+
maxParts,
615+
minParts,
616+
})
617+
).toEqual(expected);
618+
});
619+
620+
it('should match a date when the reference date is before the min', () => {
621+
// April 2, 2020 3:20 PM
622+
const refParts = { month: 4, day: 2, year: 2020, hour: 15, minute: 20 };
623+
// September 10, 2021 10:10 AM
624+
const minParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 10 };
625+
// September 10, 2021 10:15 AM
626+
const maxParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 15 };
627+
628+
// September 10, 2021 10:15 AM
629+
const expected = {
630+
month: 9,
631+
day: 10,
632+
year: 2021,
633+
hour: 10,
634+
minute: 15,
635+
ampm: 'am',
636+
dayOfWeek: undefined,
637+
};
638+
639+
expect(
640+
getClosestValidDate({
641+
refParts,
642+
monthValues: [4, 9, 11],
643+
dayValues: [10, 12, 13, 14],
644+
yearValues: [2020, 2021, 2023],
645+
hourValues: [9, 10, 11],
646+
minuteValues: [11, 12, 13, 14, 15],
647+
minParts,
648+
maxParts,
649+
})
650+
).toEqual(expected);
651+
});
652+
653+
it('should only clamp minutes if within the same day and hour as min/max', () => {
654+
// April 2, 2020 9:16 AM
655+
const refParts = { month: 4, day: 2, year: 2020, hour: 9, minute: 16 };
656+
// September 10, 2021 10:10 AM
657+
const minParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 10 };
658+
// September 10, 2021 11:15 AM
659+
const maxParts = { month: 9, day: 10, year: 2021, hour: 11, minute: 15 };
660+
661+
// September 10, 2021 10:16 AM
662+
const expected = {
663+
month: 9,
664+
day: 10,
665+
year: 2021,
666+
hour: 10,
667+
minute: 16,
668+
ampm: 'am',
669+
dayOfWeek: undefined,
670+
};
671+
672+
expect(
673+
getClosestValidDate({
674+
refParts,
675+
monthValues: [4, 9, 11],
676+
dayValues: [10, 12, 13, 14],
677+
yearValues: [2020, 2021, 2023],
678+
hourValues: [9, 10, 11],
679+
minuteValues: [10, 15, 16],
680+
minParts,
681+
maxParts,
682+
})
683+
).toEqual(expected);
684+
});
685+
686+
it('should return the closest valid date after adjusting the allowed year', () => {
687+
// April 2, 2022 9:16 AM
688+
const refParts = { month: 4, day: 2, year: 2022, hour: 9, minute: 16 };
689+
// September 10, 2021 10:10 AM
690+
const minParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 10 };
691+
// September 10, 2023 11:15 AM
692+
const maxParts = { month: 9, day: 10, year: 2023, hour: 11, minute: 15 };
693+
694+
// April 2, 2022 9:16 AM
695+
const expected = {
696+
month: 4,
697+
day: 2,
698+
year: 2022,
699+
hour: 9,
700+
minute: 16,
701+
ampm: 'am',
702+
dayOfWeek: undefined,
703+
};
704+
705+
expect(
706+
getClosestValidDate({
707+
refParts,
708+
monthValues: [4, 9, 11],
709+
dayValues: [2, 1241 10, 12, 13, 14],
710+
yearValues: [2020, 2021, 2022, 2023],
711+
hourValues: [9, 10, 11],
712+
minuteValues: [10, 15, 16],
713+
minParts,
714+
maxParts,
715+
})
716+
).toEqual(expected);
717+
});
718+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { newSpecPage } from '@stencil/core/testing';
2+
3+
import { Datetime } from '../../datetime';
4+
5+
describe('datetime: preferWheel', () => {
6+
beforeEach(() => {
7+
const mockIntersectionObserver = jest.fn();
8+
mockIntersectionObserver.mockReturnValue({
9+
observe: () => null,
10+
unobserve: () => null,
11+
disconnect: () => null,
12+
});
13+
global.IntersectionObserver = mockIntersectionObserver;
14+
});
15+
16+
it('should select the working day when clicking the confirm button', async () => {
17+
const page = await newSpecPage({
18+
components: [Datetime],
19+
html: '<ion-datetime prefer-wheel="true" max="2021" show-default-buttons="true"></ion-datetime>',
20+
});
21+
22+
const datetime = page.body.querySelector<HTMLIonDatetimeElement>('ion-datetime')!;
23+
const confirmButton = datetime.shadowRoot!.querySelector<HTMLIonButtonElement>('#confirm-button')!;
24+
25+
confirmButton.click();
26+
27+
await page.waitForChanges();
28+
29+
expect(datetime.value).toBe('2021-12-31T23:59:00');
30+
});
31+
});

0 commit comments

Comments
 (0)
0