Skip to content

Commit

Permalink
fix(datetime): prefer wheel sets working value on confirmation (#28520)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
sean-perkins and liamdebeasi committed Dec 8, 2023
1 parent 37290df commit e886e3f
Show file tree
Hide file tree
Showing 4 changed files with 327 additions and 26 deletions.
25 changes: 22 additions & 3 deletions core/src/components/datetime/datetime.tsx
Expand Up @@ -492,15 +492,24 @@ export class Datetime implements ComponentInterface {
*/
@Method()
async confirm(closeOverlay = false) {
const { isCalendarPicker, activeParts } = this;
const { isCalendarPicker, activeParts, preferWheel, workingParts } = this;

/**
* We only update the value if the presentation is not a calendar picker.
*/
if (activeParts !== undefined || !isCalendarPicker) {
const activePartsIsArray = Array.isArray(activeParts);
if (activePartsIsArray && activeParts.length === 0) {
this.setValue(undefined);
if (preferWheel) {
/**
* If the datetime is using a wheel picker, but the
* active parts are empty, then the user has confirmed the
* initial value (working parts) presented to them.
*/
this.setValue(convertDataToISO(workingParts));
} else {
this.setValue(undefined);
}
} else {
this.setValue(convertDataToISO(activeParts));
}
Expand Down Expand Up @@ -1356,11 +1365,21 @@ export class Datetime implements ComponentInterface {
const dayValues = (this.parsedDayValues = convertToArrayOfNumbers(this.dayValues));

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

this.processMinParts();
this.processMaxParts();

this.defaultParts = getClosestValidDate({
refParts: todayParts,
monthValues,
dayValues,
yearValues,
hourValues,
minuteValues,
minParts: this.minParts,
maxParts: this.maxParts,
});

this.processValue(this.value);

this.emitStyle();
Expand Down
158 changes: 158 additions & 0 deletions core/src/components/datetime/test/manipulation.spec.ts
Expand Up @@ -16,6 +16,7 @@ import {
subtractDays,
addDays,
validateParts,
getClosestValidDate,
} from '../utils/manipulation';

describe('addDays()', () => {
Expand Down Expand Up @@ -558,3 +559,160 @@ describe('validateParts()', () => {
).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 30 });
});
});

describe('getClosestValidDate()', () => {
it('should match a date with only month/day/year', () => {
// October 10, 2023
const refParts = { month: 10, day: 10, year: 2023 };
// April 10, 2021
const minParts = { month: 4, day: 10, year: 2021 };
// September 14, 2021
const maxParts = { month: 9, day: 14, year: 2021 };

// September 4, 2021
const expected = { month: 9, day: 4, year: 2021, dayOfWeek: undefined };

expect(
getClosestValidDate({
refParts,
monthValues: [2, 3, 7, 9, 10],
dayValues: [4, 15, 25],
yearValues: [2020, 2021, 2023],
maxParts,
minParts,
})
).toEqual(expected);
});

it('should match a date when the reference date is before the min', () => {
// April 2, 2020 3:20 PM
const refParts = { month: 4, day: 2, year: 2020, hour: 15, minute: 20 };
// September 10, 2021 10:10 AM
const minParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 10 };
// September 14, 2021 10:11 AM
const maxParts = { month: 9, day: 14, year: 2021, hour: 10, minute: 11 };

// September 11, 2021 11:15 AM
const expected = {
year: 2021,
day: 11,
month: 9,
hour: 11,
minute: 15,
ampm: 'am',
dayOfWeek: undefined,
};

expect(
getClosestValidDate({
refParts,
monthValues: [4, 9, 11],
dayValues: [11, 12, 13, 14],
yearValues: [2020, 2021, 2023],
hourValues: [9, 10, 11],
minuteValues: [11, 12, 13, 14, 15],
maxParts,
minParts,
})
).toEqual(expected);
});

it('should match a date when the reference date is before the min', () => {
// April 2, 2020 3:20 PM
const refParts = { month: 4, day: 2, year: 2020, hour: 15, minute: 20 };
// September 10, 2021 10:10 AM
const minParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 10 };
// September 10, 2021 10:15 AM
const maxParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 15 };

// September 10, 2021 10:15 AM
const expected = {
month: 9,
day: 10,
year: 2021,
hour: 10,
minute: 15,
ampm: 'am',
dayOfWeek: undefined,
};

expect(
getClosestValidDate({
refParts,
monthValues: [4, 9, 11],
dayValues: [10, 12, 13, 14],
yearValues: [2020, 2021, 2023],
hourValues: [9, 10, 11],
minuteValues: [11, 12, 13, 14, 15],
minParts,
maxParts,
})
).toEqual(expected);
});

it('should only clamp minutes if within the same day and hour as min/max', () => {
// April 2, 2020 9:16 AM
const refParts = { month: 4, day: 2, year: 2020, hour: 9, minute: 16 };
// September 10, 2021 10:10 AM
const minParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 10 };
// September 10, 2021 11:15 AM
const maxParts = { month: 9, day: 10, year: 2021, hour: 11, minute: 15 };

// September 10, 2021 10:16 AM
const expected = {
month: 9,
day: 10,
year: 2021,
hour: 10,
minute: 16,
ampm: 'am',
dayOfWeek: undefined,
};

expect(
getClosestValidDate({
refParts,
monthValues: [4, 9, 11],
dayValues: [10, 12, 13, 14],
yearValues: [2020, 2021, 2023],
hourValues: [9, 10, 11],
minuteValues: [10, 15, 16],
minParts,
maxParts,
})
).toEqual(expected);
});

it('should return the closest valid date after adjusting the allowed year', () => {
// April 2, 2022 9:16 AM
const refParts = { month: 4, day: 2, year: 2022, hour: 9, minute: 16 };
// September 10, 2021 10:10 AM
const minParts = { month: 9, day: 10, year: 2021, hour: 10, minute: 10 };
// September 10, 2023 11:15 AM
const maxParts = { month: 9, day: 10, year: 2023, hour: 11, minute: 15 };

// April 2, 2022 9:16 AM
const expected = {
month: 4,
day: 2,
year: 2022,
hour: 9,
minute: 16,
ampm: 'am',
dayOfWeek: undefined,
};

expect(
getClosestValidDate({
refParts,
monthValues: [4, 9, 11],
dayValues: [2, 10, 12, 13, 14],
yearValues: [2020, 2021, 2022, 2023],
hourValues: [9, 10, 11],
minuteValues: [10, 15, 16],
minParts,
maxParts,
})
).toEqual(expected);
});
});
31 changes: 31 additions & 0 deletions core/src/components/datetime/test/prefer-wheel/datetime.spec.ts
@@ -0,0 +1,31 @@
import { newSpecPage } from '@stencil/core/testing';

import { Datetime } from '../../datetime';

describe('datetime: preferWheel', () => {
beforeEach(() => {
const mockIntersectionObserver = jest.fn();
mockIntersectionObserver.mockReturnValue({
observe: () => null,
unobserve: () => null,
disconnect: () => null,
});
global.IntersectionObserver = mockIntersectionObserver;
});

it('should select the working day when clicking the confirm button', async () => {
const page = await newSpecPage({
components: [Datetime],
html: '<ion-datetime prefer-wheel="true" max="2021" show-default-buttons="true"></ion-datetime>',
});

const datetime = page.body.querySelector<HTMLIonDatetimeElement>('ion-datetime')!;
const confirmButton = datetime.shadowRoot!.querySelector<HTMLIonButtonElement>('#confirm-button')!;

confirmButton.click();

await page.waitForChanges();

expect(datetime.value).toBe('2021-12-31T23:59:00');
});
});

0 comments on commit e886e3f

Please sign in to comment.