@@ -230,9 +230,7 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
230230 /** Handles when a new date is selected. */
231231 _dateSelected ( event : MatCalendarUserEvent < number > ) {
232232 const date = event . value ;
233- const selectedYear = this . _dateAdapter . getYear ( this . activeDate ) ;
234- const selectedMonth = this . _dateAdapter . getMonth ( this . activeDate ) ;
235- const selectedDate = this . _dateAdapter . createDate ( selectedYear , selectedMonth , date ) ;
233+ const selectedDate = this . _getDateFromDayOfMonth ( date ) ;
236234 let rangeStartDate : number | null ;
237235 let rangeEndDate : number | null ;
238236
@@ -252,6 +250,26 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
252250 this . _changeDetectorRef . markForCheck ( ) ;
253251 }
254252
253+ /**
254+ * Takes the index of a calendar body cell wrapped in in an event as argument. For the date that
255+ * corresponds to the given cell, set `activeDate` to that date and fire `activeDateChange` with
256+ * that date.
257+ *
258+ * This fucntion is used to match each component's model of the active date with the calendar
259+ * body cell that was focused. It updates its value of `activeDate` synchronously and updates the
260+ * parent's value asynchonously via the `activeDateChange` event. The child component receives an
261+ * updated value asynchronously via the `activeCell` Input.
262+ */
263+ _updateActiveDate ( event : MatCalendarUserEvent < number > ) {
264+ const month = event . value ;
265+ const oldActiveDate = this . _activeDate ;
266+ this . activeDate = this . _getDateFromDayOfMonth ( month ) ;
267+
268+ if ( this . _dateAdapter . compareDate ( oldActiveDate , this . activeDate ) ) {
269+ this . activeDateChange . emit ( this . _activeDate ) ;
270+ }
271+ }
272+
255273 /** Handles keydown events on the calendar body when calendar is in month view. */
256274 _handleCalendarBodyKeydown ( event : KeyboardEvent ) : void {
257275 // TODO(mmalerba): We currently allow keyboard navigation to disabled dates, but just prevent
@@ -327,9 +345,10 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
327345
328346 if ( this . _dateAdapter . compareDate ( oldActiveDate , this . activeDate ) ) {
329347 this . activeDateChange . emit ( this . activeDate ) ;
348+
349+ this . _focusActiveCellAfterViewChecked ( ) ;
330350 }
331351
332- this . _focusActiveCell ( ) ;
333352 // Prevent unexpected default actions such as form submission.
334353 event . preventDefault ( ) ;
335354 }
@@ -376,6 +395,11 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
376395 this . _matCalendarBody . _focusActiveCell ( movePreview ) ;
377396 }
378397
398+ /** Focuses the active cell after change detection has run and the microtask queue is empty. */
399+ _focusActiveCellAfterViewChecked ( ) {
400+ this . _matCalendarBody . _scheduleFocusActiveCellAfterViewChecked ( ) ;
401+ }
402+
379403 /** Called when the user has activated a new cell and the preview needs to be updated. */
380404 _previewChanged ( { event, value : cell } : MatCalendarUserEvent < MatCalendarCell < D > | null > ) {
381405 if ( this . _rangeStrategy ) {
@@ -398,6 +422,18 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
398422 }
399423 }
400424
425+ /**
426+ * Takes a day of the month and returns a new date in the same month and year as the currently
427+ * active date. The returned date will have the same day of the month as the argument date.
428+ */
429+ private _getDateFromDayOfMonth ( dayOfMonth : number ) : D {
430+ return this . _dateAdapter . createDate (
431+ this . _dateAdapter . getYear ( this . activeDate ) ,
432+ this . _dateAdapter . getMonth ( this . activeDate ) ,
433+ dayOfMonth ,
434+ ) ;
435+ }
436+
401437 /** Initializes the weekdays. */
402438 private _initWeekdays ( ) {
403439 const firstDayOfWeek = this . _dateAdapter . getFirstDayOfWeek ( ) ;
0 commit comments