diff --git a/src/material/datepicker/calendar.spec.ts b/src/material/datepicker/calendar.spec.ts index 2bbfb3f747c2..980550d08918 100644 --- a/src/material/datepicker/calendar.spec.ts +++ b/src/material/datepicker/calendar.spec.ts @@ -283,6 +283,45 @@ describe('MatCalendar', () => { }); }); + it('should re-render the month view when the locale changes', + inject([DateAdapter], (adapter: DateAdapter) => { + fixture.detectChanges(); + spyOn(calendarInstance.monthView, '_init').and.callThrough(); + + adapter.setLocale('bg-BG'); + fixture.detectChanges(); + + expect(calendarInstance.monthView._init).toHaveBeenCalled(); + })); + + it('should re-render the year view when the locale changes', + inject([DateAdapter], (adapter: DateAdapter) => { + periodButton.click(); + fixture.detectChanges(); + + (calendarElement.querySelector('.mat-calendar-body-active') as HTMLElement).click(); + fixture.detectChanges(); + + spyOn(calendarInstance.yearView, '_init').and.callThrough(); + + adapter.setLocale('bg-BG'); + fixture.detectChanges(); + + expect(calendarInstance.yearView._init).toHaveBeenCalled(); + })); + + it('should re-render the multi-year view when the locale changes', + inject([DateAdapter], (adapter: DateAdapter) => { + periodButton.click(); + fixture.detectChanges(); + + spyOn(calendarInstance.multiYearView, '_init').and.callThrough(); + + adapter.setLocale('bg-BG'); + fixture.detectChanges(); + + expect(calendarInstance.multiYearView._init).toHaveBeenCalled(); + })); }); describe('calendar with min and max date', () => { diff --git a/src/material/datepicker/month-view.ts b/src/material/datepicker/month-view.ts index fc5836bd9a71..3d414fe08eac 100644 --- a/src/material/datepicker/month-view.ts +++ b/src/material/datepicker/month-view.ts @@ -30,11 +30,14 @@ import { Output, ViewEncapsulation, ViewChild, + OnDestroy, } from '@angular/core'; import {DateAdapter, MAT_DATE_FORMATS, MatDateFormats} from '@angular/material/core'; import {Directionality} from '@angular/cdk/bidi'; import {MatCalendarBody, MatCalendarCell, MatCalendarCellCssClasses} from './calendar-body'; import {createMissingDateImplError} from './datepicker-errors'; +import {Subscription} from 'rxjs'; +import {startWith} from 'rxjs/operators'; const DAYS_PER_WEEK = 7; @@ -51,7 +54,9 @@ const DAYS_PER_WEEK = 7; encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush }) -export class MatMonthView implements AfterContentInit { +export class MatMonthView implements AfterContentInit, OnDestroy { + private _rerenderSubscription = Subscription.EMPTY; + /** * The date to display in this month view (everything other than the month and year is ignored). */ @@ -147,7 +152,13 @@ export class MatMonthView implements AfterContentInit { } ngAfterContentInit() { - this._init(); + this._rerenderSubscription = this._dateAdapter.localeChanges + .pipe(startWith(null)) + .subscribe(() => this._init()); + } + + ngOnDestroy() { + this._rerenderSubscription.unsubscribe(); } /** Handles when a new date is selected. */ diff --git a/src/material/datepicker/multi-year-view.ts b/src/material/datepicker/multi-year-view.ts index fa3a8886529f..328cdf6445da 100644 --- a/src/material/datepicker/multi-year-view.ts +++ b/src/material/datepicker/multi-year-view.ts @@ -29,11 +29,14 @@ import { Output, ViewChild, ViewEncapsulation, + OnDestroy, } from '@angular/core'; import {DateAdapter} from '@angular/material/core'; import {Directionality} from '@angular/cdk/bidi'; import {MatCalendarBody, MatCalendarCell} from './calendar-body'; import {createMissingDateImplError} from './datepicker-errors'; +import {Subscription} from 'rxjs'; +import {startWith} from 'rxjs/operators'; export const yearsPerPage = 24; @@ -50,7 +53,9 @@ export const yearsPerRow = 4; encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush }) -export class MatMultiYearView implements AfterContentInit { +export class MatMultiYearView implements AfterContentInit, OnDestroy { + private _rerenderSubscription = Subscription.EMPTY; + /** The date to display in this multi-year view (everything other than the year is ignored). */ @Input() get activeDate(): D { return this._activeDate; } @@ -127,7 +132,13 @@ export class MatMultiYearView implements AfterContentInit { } ngAfterContentInit() { - this._init(); + this._rerenderSubscription = this._dateAdapter.localeChanges + .pipe(startWith(null)) + .subscribe(() => this._init()); + } + + ngOnDestroy() { + this._rerenderSubscription.unsubscribe(); } /** Initializes this multi-year view. */ diff --git a/src/material/datepicker/year-view.ts b/src/material/datepicker/year-view.ts index 5d2ffe15bc8c..769eb328bf01 100644 --- a/src/material/datepicker/year-view.ts +++ b/src/material/datepicker/year-view.ts @@ -30,11 +30,14 @@ import { Output, ViewChild, ViewEncapsulation, + OnDestroy, } from '@angular/core'; import {DateAdapter, MAT_DATE_FORMATS, MatDateFormats} from '@angular/material/core'; import {Directionality} from '@angular/cdk/bidi'; import {MatCalendarBody, MatCalendarCell} from './calendar-body'; import {createMissingDateImplError} from './datepicker-errors'; +import {Subscription} from 'rxjs'; +import {startWith} from 'rxjs/operators'; /** * An internal component used to display a single year in the datepicker. @@ -47,7 +50,9 @@ import {createMissingDateImplError} from './datepicker-errors'; encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush }) -export class MatYearView implements AfterContentInit { +export class MatYearView implements AfterContentInit, OnDestroy { + private _rerenderSubscription = Subscription.EMPTY; + /** The date to display in this year view (everything other than the year is ignored). */ @Input() get activeDate(): D { return this._activeDate; } @@ -132,7 +137,13 @@ export class MatYearView implements AfterContentInit { } ngAfterContentInit() { - this._init(); + this._rerenderSubscription = this._dateAdapter.localeChanges + .pipe(startWith(null)) + .subscribe(() => this._init()); + } + + ngOnDestroy() { + this._rerenderSubscription.unsubscribe(); } /** Handles when a new month is selected. */ diff --git a/tools/public_api_guard/material/datepicker.d.ts b/tools/public_api_guard/material/datepicker.d.ts index ab9d4defe69e..eb1c86a379c9 100644 --- a/tools/public_api_guard/material/datepicker.d.ts +++ b/tools/public_api_guard/material/datepicker.d.ts @@ -244,7 +244,7 @@ export declare class MatDatepickerToggleIcon { static ɵfac: i0.ɵɵFactoryDef; } -export declare class MatMonthView implements AfterContentInit { +export declare class MatMonthView implements AfterContentInit, OnDestroy { _dateAdapter: DateAdapter; _firstWeekOffset: number; _matCalendarBody: MatCalendarBody; @@ -271,11 +271,12 @@ export declare class MatMonthView implements AfterContentInit { _handleCalendarBodyKeydown(event: KeyboardEvent): void; _init(): void; ngAfterContentInit(): void; + ngOnDestroy(): void; static ɵcmp: i0.ɵɵComponentDefWithMeta, "mat-month-view", ["matMonthView"], { 'activeDate': "activeDate", 'selected': "selected", 'minDate': "minDate", 'maxDate': "maxDate", 'dateFilter': "dateFilter", 'dateClass': "dateClass" }, { 'selectedChange': "selectedChange", '_userSelection': "_userSelection", 'activeDateChange': "activeDateChange" }, never>; static ɵfac: i0.ɵɵFactoryDef>; } -export declare class MatMultiYearView implements AfterContentInit { +export declare class MatMultiYearView implements AfterContentInit, OnDestroy { _dateAdapter: DateAdapter; _matCalendarBody: MatCalendarBody; _selectedYear: number | null; @@ -296,11 +297,12 @@ export declare class MatMultiYearView implements AfterContentInit { _init(): void; _yearSelected(year: number): void; ngAfterContentInit(): void; + ngOnDestroy(): void; static ɵcmp: i0.ɵɵComponentDefWithMeta, "mat-multi-year-view", ["matMultiYearView"], { 'activeDate': "activeDate", 'selected': "selected", 'minDate': "minDate", 'maxDate': "maxDate", 'dateFilter': "dateFilter" }, { 'selectedChange': "selectedChange", 'yearSelected': "yearSelected", 'activeDateChange': "activeDateChange" }, never>; static ɵfac: i0.ɵɵFactoryDef>; } -export declare class MatYearView implements AfterContentInit { +export declare class MatYearView implements AfterContentInit, OnDestroy { _dateAdapter: DateAdapter; _matCalendarBody: MatCalendarBody; _months: MatCalendarCell[][]; @@ -321,6 +323,7 @@ export declare class MatYearView implements AfterContentInit { _init(): void; _monthSelected(month: number): void; ngAfterContentInit(): void; + ngOnDestroy(): void; static ɵcmp: i0.ɵɵComponentDefWithMeta, "mat-year-view", ["matYearView"], { 'activeDate': "activeDate", 'selected': "selected", 'minDate': "minDate", 'maxDate': "maxDate", 'dateFilter': "dateFilter" }, { 'selectedChange': "selectedChange", 'monthSelected': "monthSelected", 'activeDateChange': "activeDateChange" }, never>; static ɵfac: i0.ɵɵFactoryDef>; }