Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(datetime): preferWheel respects column ordering by locale #25726

Merged
merged 4 commits into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion core/src/components/datetime/datetime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1522,7 +1522,27 @@ export class Datetime implements ComponentInterface {
? getYearColumnData(this.todayParts, this.minParts, this.maxParts, this.parsedYearValues)
: [];

return [this.renderMonthPickerColumn(months), this.renderDayPickerColumn(days), this.renderYearPickerColumn(years)];
/**
* Certain locales show the day before the month.
*/
const showMonthFirst = isMonthFirstLocale(this.locale, { month: 'numeric', day: 'numeric' });

let renderArray = [];
if (showMonthFirst) {
renderArray = [
this.renderMonthPickerColumn(months),
this.renderDayPickerColumn(days),
this.renderYearPickerColumn(years),
];
} else {
renderArray = [
this.renderDayPickerColumn(days),
this.renderMonthPickerColumn(months),
this.renderYearPickerColumn(years),
];
}

return renderArray;
}

private renderDayPickerColumn(days: PickerColumnItem[]) {
Expand Down
78 changes: 58 additions & 20 deletions core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,26 +89,64 @@ test.describe('datetime: prefer wheel', () => {
expect(await yearValues.count()).toBe(3);
expect(await dayValues.count()).toBe(5);
});
test('should correctly localize the date data', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="ja-JP"
min="2022-01-01"
max="2022-03-01"
day-values="1,2,3"
value="2022-01-01"
></ion-datetime>
`);

await page.waitForSelector('.datetime-ready');

const monthValues = page.locator('.month-column .picker-item:not(.picker-item-empty)');
const dayValues = page.locator('.day-column .picker-item:not(.picker-item-empty)');

expect(monthValues).toHaveText(['1月', '2月', '3月']);
expect(dayValues).toHaveText(['1日', '2日', '3日']);
test.describe('datetime: date wheel localization', () => {
test('should correctly localize the date data', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="ja-JP"
min="2022-01-01"
max="2022-03-01"
day-values="1,2,3"
value="2022-01-01"
></ion-datetime>
`);

await page.waitForSelector('.datetime-ready');

const monthValues = page.locator('.month-column .picker-item:not(.picker-item-empty)');
const dayValues = page.locator('.day-column .picker-item:not(.picker-item-empty)');

expect(monthValues).toHaveText(['1月', '2月', '3月']);
expect(dayValues).toHaveText(['1日', '2日', '3日']);
});
test('should render the columns according to locale - en-US', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="en-US"
value="2022-01-01"
></ion-datetime>
`);

await page.waitForSelector('.datetime-ready');

const columns = page.locator('ion-picker-column-internal');

await expect(columns.nth(0)).toHaveClass(/month-column/);
await expect(columns.nth(1)).toHaveClass(/day-column/);
await expect(columns.nth(2)).toHaveClass(/year-column/);
});
test('should render the columns according to locale - en-GB', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="en-GB"
value="2022-01-01"
></ion-datetime>
`);

await page.waitForSelector('.datetime-ready');

const columns = page.locator('ion-picker-column-internal');

await expect(columns.nth(0)).toHaveClass(/day-column/);
await expect(columns.nth(1)).toHaveClass(/month-column/);
await expect(columns.nth(2)).toHaveClass(/year-column/);
});
});
});
test.describe('datetime: date-time wheel rendering', () => {
Expand Down
15 changes: 13 additions & 2 deletions core/src/components/datetime/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,19 @@ export const getNumDaysInMonth = (month: number, year: number) => {
* others display year then month.
* We can use Intl.DateTimeFormat to determine
* the ordering for each locale.
* The formatOptions param can be used to customize
* which pieces of a date to compare against the month
* with. For example, some locales render dd/mm/yyyy
* while others render mm/dd/yyyy. This function can be
* used for variations of the same "month first" check.
*/
export const isMonthFirstLocale = (locale: string) => {
export const isMonthFirstLocale = (
locale: string,
formatOptions: Intl.DateTimeFormatOptions = {
month: 'numeric',
year: 'numeric',
}
) => {
/**
* By setting month and year we guarantee that only
* month, year, and literal (slashes '/', for example)
Expand All @@ -88,7 +99,7 @@ export const isMonthFirstLocale = (locale: string) => {
*
* This ordering can be controlled by customizing the locale property.
*/
const parts = new Intl.DateTimeFormat(locale, { month: 'numeric', year: 'numeric' }).formatToParts(new Date());
const parts = new Intl.DateTimeFormat(locale, formatOptions).formatToParts(new Date());

return parts[0].type === 'month';
};
Expand Down