mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix(datetime): selecting days updates value (#26121)
This commit is contained in:
@@ -561,7 +561,7 @@ export class Datetime implements ComponentInterface {
|
||||
* "activePartsClone" and then falling back to
|
||||
* today's DatetimeParts if no active date is selected.
|
||||
*/
|
||||
private getDefaultPart = () => {
|
||||
private getDefaultPart = (): DatetimeParts => {
|
||||
const { activePartsClone, todayParts } = this;
|
||||
|
||||
const firstPart = Array.isArray(activePartsClone) ? activePartsClone[0] : activePartsClone;
|
||||
@@ -1393,7 +1393,9 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private renderCombinedDatePickerColumn() {
|
||||
const { activeParts, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
|
||||
const { workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
|
||||
|
||||
const activePart = this.getDefaultPart();
|
||||
|
||||
/**
|
||||
* By default, generate a range of 3 months:
|
||||
@@ -1489,12 +1491,10 @@ export class Datetime implements ComponentInterface {
|
||||
...findPart,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activeParts)) {
|
||||
this.setActiveParts({
|
||||
...activeParts,
|
||||
...findPart,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
...findPart,
|
||||
});
|
||||
|
||||
// We can re-attach the scroll listener after
|
||||
// the working parts have been updated.
|
||||
@@ -1583,7 +1583,9 @@ export class Datetime implements ComponentInterface {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { activeParts, workingParts } = this;
|
||||
const { workingParts } = this;
|
||||
|
||||
const activePart = this.getDefaultPart();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
@@ -1605,12 +1607,10 @@ export class Datetime implements ComponentInterface {
|
||||
day: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activeParts)) {
|
||||
this.setActiveParts({
|
||||
...activeParts,
|
||||
day: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
day: ev.detail.value,
|
||||
});
|
||||
|
||||
// We can re-attach the scroll listener after
|
||||
// the working parts have been updated.
|
||||
@@ -1627,7 +1627,9 @@ export class Datetime implements ComponentInterface {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { activeParts, workingParts } = this;
|
||||
const { workingParts } = this;
|
||||
|
||||
const activePart = this.getDefaultPart();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
@@ -1649,12 +1651,10 @@ export class Datetime implements ComponentInterface {
|
||||
month: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activeParts)) {
|
||||
this.setActiveParts({
|
||||
...activeParts,
|
||||
month: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
month: ev.detail.value,
|
||||
});
|
||||
|
||||
// We can re-attach the scroll listener after
|
||||
// the working parts have been updated.
|
||||
@@ -1670,7 +1670,9 @@ export class Datetime implements ComponentInterface {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { activeParts, workingParts } = this;
|
||||
const { workingParts } = this;
|
||||
|
||||
const activePart = this.getDefaultPart();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
@@ -1692,12 +1694,10 @@ export class Datetime implements ComponentInterface {
|
||||
year: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activeParts)) {
|
||||
this.setActiveParts({
|
||||
...activeParts,
|
||||
year: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
year: ev.detail.value,
|
||||
});
|
||||
|
||||
// We can re-attach the scroll listener after
|
||||
// the working parts have been updated.
|
||||
@@ -1750,12 +1750,10 @@ export class Datetime implements ComponentInterface {
|
||||
hour: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activePart)) {
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
hour: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
hour: ev.detail.value,
|
||||
});
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
@@ -1780,12 +1778,10 @@ export class Datetime implements ComponentInterface {
|
||||
minute: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activePart)) {
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
minute: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
minute: ev.detail.value,
|
||||
});
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
@@ -1816,13 +1812,11 @@ export class Datetime implements ComponentInterface {
|
||||
hour,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activePart)) {
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
ampm: ev.detail.value,
|
||||
hour,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
ampm: ev.detail.value,
|
||||
hour,
|
||||
});
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
@@ -1914,6 +1908,8 @@ export class Datetime implements ComponentInterface {
|
||||
// can free-scroll the calendar.
|
||||
const isWorkingMonth = this.workingParts.month === month && this.workingParts.year === year;
|
||||
|
||||
const activePart = this.getDefaultPart();
|
||||
|
||||
return (
|
||||
<div
|
||||
// Non-visible months should be hidden from screen readers
|
||||
@@ -1998,7 +1994,7 @@ export class Datetime implements ComponentInterface {
|
||||
);
|
||||
} else {
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
...activePart,
|
||||
month,
|
||||
day,
|
||||
year,
|
||||
|
||||
@@ -72,6 +72,39 @@ test.describe('datetime: selecting a day', () => {
|
||||
|
||||
await expect(activeDay).toHaveText('13');
|
||||
});
|
||||
test('should set both date and time when no value is initially set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime locale="en-US" presentation="date-time"></ion-datetime>
|
||||
|
||||
<script>
|
||||
const mockToday = '2022-10-10T16:22';
|
||||
Date = class extends Date {
|
||||
constructor(...args) {
|
||||
if (args.length === 0) {
|
||||
super(mockToday)
|
||||
} else {
|
||||
super(...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
|
||||
// Oct 1, 2022
|
||||
await page.click('.calendar-day[data-month="10"][data-year="2022"][data-day="1"]');
|
||||
|
||||
await ionChange.next();
|
||||
|
||||
const value = await datetime.evaluate((el: HTMLIonDatetimeElement) => el.value);
|
||||
await expect(typeof value).toBe('string');
|
||||
|
||||
// Check to make sure value includes current time
|
||||
await expect(value!.includes('2022-10-01T16:22')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('datetime: confirm date', () => {
|
||||
|
||||
@@ -112,6 +112,64 @@ test.describe('datetime: prefer wheel', () => {
|
||||
expect(await yearValues.count()).toBe(3);
|
||||
expect(await dayValues.count()).toBe(5);
|
||||
});
|
||||
test('selecting month should update value when no value is set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
presentation="date"
|
||||
prefer-wheel="true"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const monthValues = page.locator('.month-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
// Change month value
|
||||
await monthValues.nth(0).click();
|
||||
|
||||
await ionChange.next();
|
||||
});
|
||||
test('selecting day should update value when no value is set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
presentation="date"
|
||||
prefer-wheel="true"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const dayValues = page.locator('.day-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
// Change day value
|
||||
await dayValues.nth(0).click();
|
||||
|
||||
await ionChange.next();
|
||||
});
|
||||
test('selecting year should update value when no value is set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
presentation="date"
|
||||
prefer-wheel="true"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const yearValues = page.locator('.year-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
/**
|
||||
* Change year value
|
||||
* The 0th index is the current
|
||||
* year, so select something other than that.
|
||||
*/
|
||||
await yearValues.nth(10).click();
|
||||
|
||||
await ionChange.next();
|
||||
});
|
||||
test.describe('datetime: date wheel localization', () => {
|
||||
test('should correctly localize the date data', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
@@ -314,6 +372,24 @@ test.describe('datetime: prefer wheel', () => {
|
||||
|
||||
expect(await dayValues.count()).toBe(15);
|
||||
});
|
||||
test('selecting date should update value when no value is set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
presentation="date-time"
|
||||
prefer-wheel="true"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
// Change day/month value
|
||||
await dayValues.nth(0).click();
|
||||
|
||||
await ionChange.next();
|
||||
});
|
||||
});
|
||||
test.describe('datetime: time-date wheel', () => {
|
||||
test.beforeEach(({ skip }) => {
|
||||
|
||||
Reference in New Issue
Block a user