diff --git a/src/lib/datepicker/calendar.spec.ts b/src/lib/datepicker/calendar.spec.ts index c4fb499e5505..7dd4829d333a 100644 --- a/src/lib/datepicker/calendar.spec.ts +++ b/src/lib/datepicker/calendar.spec.ts @@ -27,6 +27,7 @@ import { SEP, } from '@angular/material/core'; import {By} from '@angular/platform-browser'; +import {Direction, Directionality} from '@angular/cdk/bidi'; import {MatButtonModule} from '../button/index'; import {MatCalendar} from './calendar'; import {MatCalendarBody} from './calendar-body'; @@ -36,6 +37,8 @@ import {MatYearView} from './year-view'; describe('MatCalendar', () => { + let dir: {value: Direction}; + beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ @@ -55,6 +58,7 @@ describe('MatCalendar', () => { ], providers: [ MatDatepickerIntl, + {provide: Directionality, useFactory: () => dir = {value: 'ltr'}} ], }); @@ -204,6 +208,20 @@ describe('MatCalendar', () => { expect(calendarInstance._activeDate).toEqual(new Date(2016, DEC, 31)); }); + it('should increment date on left arrow press in rtl', () => { + dir.value = 'rtl'; + + dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW); + fixture.detectChanges(); + + expect(calendarInstance._activeDate).toEqual(new Date(2017, FEB, 1)); + + dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW); + fixture.detectChanges(); + + expect(calendarInstance._activeDate).toEqual(new Date(2017, FEB, 2)); + }); + it('should increment date on right arrow press', () => { dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW); fixture.detectChanges(); @@ -216,6 +234,23 @@ describe('MatCalendar', () => { expect(calendarInstance._activeDate).toEqual(new Date(2017, FEB, 2)); }); + it('should decrement date on right arrow press in rtl', () => { + dir.value = 'rtl'; + + dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW); + fixture.detectChanges(); + + expect(calendarInstance._activeDate).toEqual(new Date(2017, JAN, 30)); + + calendarInstance._activeDate = new Date(2017, JAN, 1); + fixture.detectChanges(); + + dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW); + fixture.detectChanges(); + + expect(calendarInstance._activeDate).toEqual(new Date(2016, DEC, 31)); + }); + it('should go up a row on up arrow press', () => { dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW); fixture.detectChanges(); @@ -326,6 +361,20 @@ describe('MatCalendar', () => { expect(calendarInstance._activeDate).toEqual(new Date(2016, NOV, 30)); }); + it('should increment month on left arrow press in rtl', () => { + dir.value = 'rtl'; + + dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW); + fixture.detectChanges(); + + expect(calendarInstance._activeDate).toEqual(new Date(2017, FEB, 28)); + + dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW); + fixture.detectChanges(); + + expect(calendarInstance._activeDate).toEqual(new Date(2017, MAR, 28)); + }); + it('should increment month on right arrow press', () => { dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW); fixture.detectChanges(); @@ -338,6 +387,20 @@ describe('MatCalendar', () => { expect(calendarInstance._activeDate).toEqual(new Date(2017, MAR, 28)); }); + it('should decrement month on right arrow press in rtl', () => { + dir.value = 'rtl'; + + dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW); + fixture.detectChanges(); + + expect(calendarInstance._activeDate).toEqual(new Date(2016, DEC, 31)); + + dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW); + fixture.detectChanges(); + + expect(calendarInstance._activeDate).toEqual(new Date(2016, NOV, 30)); + }); + it('should go up a row on up arrow press', () => { dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW); fixture.detectChanges(); diff --git a/src/lib/datepicker/calendar.ts b/src/lib/datepicker/calendar.ts index d7d76ddbf64e..14ed0795c58c 100644 --- a/src/lib/datepicker/calendar.ts +++ b/src/lib/datepicker/calendar.ts @@ -42,6 +42,7 @@ import {createMissingDateImplError} from './datepicker-errors'; import {MatDatepickerIntl} from './datepicker-intl'; import {MatMonthView} from './month-view'; import {MatYearView} from './year-view'; +import {Directionality} from '@angular/cdk/bidi'; /** @@ -162,7 +163,8 @@ export class MatCalendar implements AfterContentInit, OnDestroy, OnChanges { private _ngZone: NgZone, @Optional() private _dateAdapter: DateAdapter, @Optional() @Inject(MAT_DATE_FORMATS) private _dateFormats: MatDateFormats, - changeDetectorRef: ChangeDetectorRef) { + changeDetectorRef: ChangeDetectorRef, + @Optional() private _dir?: Directionality) { if (!this._dateAdapter) { throw createMissingDateImplError('DateAdapter'); @@ -277,12 +279,14 @@ export class MatCalendar implements AfterContentInit, OnDestroy, OnChanges { /** Handles keydown events on the calendar body when calendar is in month view. */ private _handleCalendarBodyKeydownInMonthView(event: KeyboardEvent): void { + const isRtl = this._isRtl(); + switch (event.keyCode) { case LEFT_ARROW: - this._activeDate = this._dateAdapter.addCalendarDays(this._activeDate, -1); + this._activeDate = this._dateAdapter.addCalendarDays(this._activeDate, isRtl ? 1 : -1); break; case RIGHT_ARROW: - this._activeDate = this._dateAdapter.addCalendarDays(this._activeDate, 1); + this._activeDate = this._dateAdapter.addCalendarDays(this._activeDate, isRtl ? -1 : 1); break; case UP_ARROW: this._activeDate = this._dateAdapter.addCalendarDays(this._activeDate, -7); @@ -329,12 +333,14 @@ export class MatCalendar implements AfterContentInit, OnDestroy, OnChanges { /** Handles keydown events on the calendar body when calendar is in year view. */ private _handleCalendarBodyKeydownInYearView(event: KeyboardEvent): void { + const isRtl = this._isRtl(); + switch (event.keyCode) { case LEFT_ARROW: - this._activeDate = this._dateAdapter.addCalendarMonths(this._activeDate, -1); + this._activeDate = this._dateAdapter.addCalendarMonths(this._activeDate, isRtl ? 1 : -1); break; case RIGHT_ARROW: - this._activeDate = this._dateAdapter.addCalendarMonths(this._activeDate, 1); + this._activeDate = this._dateAdapter.addCalendarMonths(this._activeDate, isRtl ? -1 : 1); break; case UP_ARROW: this._activeDate = this._prevMonthInSameCol(this._activeDate); @@ -396,4 +402,9 @@ export class MatCalendar implements AfterContentInit, OnDestroy, OnChanges { private _getValidDateOrNull(obj: any): D | null { return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null; } + + /** Determines whether the user has the RTL layout direction. */ + private _isRtl() { + return this._dir && this._dir.value === 'rtl'; + } }