Skip to content

Commit

Permalink
Revert "fix(material/datepicker): update active date on focusing a ca…
Browse files Browse the repository at this point in the history
…lendar cell (#24279)" (#24380)

This reverts commit 052b97d.

(cherry picked from commit e04e4a7)
  • Loading branch information
zarend committed Feb 8, 2022
1 parent f5199ee commit 60abc41
Show file tree
Hide file tree
Showing 12 changed files with 33 additions and 262 deletions.
3 changes: 1 addition & 2 deletions src/material/datepicker/calendar-body.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@
[attr.aria-disabled]="!item.enabled || null"
[attr.aria-pressed]="_isSelected(item.compareValue)"
[attr.aria-current]="todayValue === item.compareValue ? 'date' : null"
(click)="_cellClicked(item, $event)"
(focus)="_emitActiveDateChange(item, $event)">
(click)="_cellClicked(item, $event)">
<div class="mat-calendar-body-cell-content mat-focus-indicator"
[class.mat-calendar-body-selected]="_isSelected(item.compareValue)"
[class.mat-calendar-body-comparison-identical]="_isComparisonIdentical(item.compareValue)"
Expand Down
28 changes: 1 addition & 27 deletions src/material/datepicker/calendar-body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
OnChanges,
SimpleChanges,
OnDestroy,
AfterViewChecked,
} from '@angular/core';
import {take} from 'rxjs/operators';

Expand Down Expand Up @@ -68,18 +67,13 @@ export interface MatCalendarUserEvent<D> {
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MatCalendarBody implements OnChanges, OnDestroy, AfterViewChecked {
export class MatCalendarBody implements OnChanges, OnDestroy {
/**
* Used to skip the next focus event when rendering the preview range.
* We need a flag like this, because some browsers fire focus events asynchronously.
*/
private _skipNextFocus: boolean;

/**
* Used to focus the active cell after change detection has run.
*/
private _focusActiveCellAfterViewChecked = false;

/** The label for the table. (e.g. "Jan 2017"). */
@Input() label: string;

Expand All @@ -104,13 +98,6 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterViewChecked {
/** The cell number of the active cell in the table. */
@Input() activeCell: number = 0;

ngAfterViewChecked() {
if (this._focusActiveCellAfterViewChecked) {
this._focusActiveCell();
this._focusActiveCellAfterViewChecked = false;
}
}

/** Whether a range is being selected. */
@Input() isRange: boolean = false;

Expand Down Expand Up @@ -140,8 +127,6 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterViewChecked {
MatCalendarUserEvent<MatCalendarCell | null>
>();

@Output() readonly activeDateChange = new EventEmitter<MatCalendarUserEvent<number>>();

/** The number of blank cells to put at the beginning for the first row. */
_firstRowOffset: number;

Expand All @@ -168,12 +153,6 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterViewChecked {
}
}

_emitActiveDateChange(cell: MatCalendarCell, event: FocusEvent): void {
if (cell.enabled) {
this.activeDateChange.emit({value: cell.value, event});
}
}

/** Returns whether a cell should be marked as selected. */
_isSelected(value: number) {
return this.startValue === value || this.endValue === value;
Expand Down Expand Up @@ -235,11 +214,6 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterViewChecked {
});
}

/** Focuses the active cell after change detection has run and the microtask queue is empty. */
_scheduleFocusActiveCellAfterViewChecked() {
this._focusActiveCellAfterViewChecked = true;
}

/** Gets whether a value is the start of the main range. */
_isRangeStart(value: number) {
return isStart(value, this.startValue, this.endValue);
Expand Down
1 change: 0 additions & 1 deletion src/material/datepicker/month-view.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
[labelMinRequiredCells]="3"
[activeCell]="_dateAdapter.getDate(activeDate) - 1"
(selectedValueChange)="_dateSelected($event)"
(activeDateChange)="_updateActiveDate($event)"
(previewChange)="_previewChanged($event)"
(keyup)="_handleCalendarBodyKeyup($event)"
(keydown)="_handleCalendarBodyKeydown($event)">
Expand Down
24 changes: 0 additions & 24 deletions src/material/datepicker/month-view.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,30 +520,6 @@ describe('MatMonthView', () => {
);
},
);

it('should go to month that is focused', () => {
const jan11Cell = fixture.debugElement.nativeElement.querySelector(
'[data-mat-row="1"][data-mat-col="3"] button',
) as HTMLElement;

dispatchFakeEvent(jan11Cell, 'focus');
fixture.detectChanges();

expect(calendarInstance.date).toEqual(new Date(2017, JAN, 11));
});

it('should not call `.focus()` when the active date is focused', () => {
const jan5Cell = fixture.debugElement.nativeElement.querySelector(
'[data-mat-row="0"][data-mat-col="4"] button',
) as HTMLElement;
const focusSpy = (jan5Cell.focus = jasmine.createSpy('cellFocused'));

dispatchFakeEvent(jan5Cell, 'focus');
fixture.detectChanges();

expect(calendarInstance.date).toEqual(new Date(2017, JAN, 5));
expect(focusSpy).not.toHaveBeenCalled();
});
});
});
});
Expand Down
44 changes: 4 additions & 40 deletions src/material/datepicker/month-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
/** Handles when a new date is selected. */
_dateSelected(event: MatCalendarUserEvent<number>) {
const date = event.value;
const selectedDate = this._getDateFromDayOfMonth(date);
const selectedYear = this._dateAdapter.getYear(this.activeDate);
const selectedMonth = this._dateAdapter.getMonth(this.activeDate);
const selectedDate = this._dateAdapter.createDate(selectedYear, selectedMonth, date);
let rangeStartDate: number | null;
let rangeEndDate: number | null;

Expand All @@ -250,26 +252,6 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
this._changeDetectorRef.markForCheck();
}

/**
* Takes the index of a calendar body cell wrapped in in an event as argument. For the date that
* corresponds to the given cell, set `activeDate` to that date and fire `activeDateChange` with
* that date.
*
* This fucntion is used to match each component's model of the active date with the calendar
* body cell that was focused. It updates its value of `activeDate` synchronously and updates the
* parent's value asynchonously via the `activeDateChange` event. The child component receives an
* updated value asynchronously via the `activeCell` Input.
*/
_updateActiveDate(event: MatCalendarUserEvent<number>) {
const month = event.value;
const oldActiveDate = this._activeDate;
this.activeDate = this._getDateFromDayOfMonth(month);

if (this._dateAdapter.compareDate(oldActiveDate, this.activeDate)) {
this.activeDateChange.emit(this._activeDate);
}
}

/** Handles keydown events on the calendar body when calendar is in month view. */
_handleCalendarBodyKeydown(event: KeyboardEvent): void {
// TODO(mmalerba): We currently allow keyboard navigation to disabled dates, but just prevent
Expand Down Expand Up @@ -345,10 +327,9 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {

if (this._dateAdapter.compareDate(oldActiveDate, this.activeDate)) {
this.activeDateChange.emit(this.activeDate);

this._focusActiveCellAfterViewChecked();
}

this._focusActiveCell();
// Prevent unexpected default actions such as form submission.
event.preventDefault();
}
Expand Down Expand Up @@ -395,11 +376,6 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
this._matCalendarBody._focusActiveCell(movePreview);
}

/** Focuses the active cell after change detection has run and the microtask queue is empty. */
_focusActiveCellAfterViewChecked() {
this._matCalendarBody._scheduleFocusActiveCellAfterViewChecked();
}

/** Called when the user has activated a new cell and the preview needs to be updated. */
_previewChanged({event, value: cell}: MatCalendarUserEvent<MatCalendarCell<D> | null>) {
if (this._rangeStrategy) {
Expand All @@ -422,18 +398,6 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
}
}

/**
* Takes a day of the month and returns a new date in the same month and year as the currently
* active date. The returned date will have the same day of the month as the argument date.
*/
private _getDateFromDayOfMonth(dayOfMonth: number): D {
return this._dateAdapter.createDate(
this._dateAdapter.getYear(this.activeDate),
this._dateAdapter.getMonth(this.activeDate),
dayOfMonth,
);
}

/** Initializes the weekdays. */
private _initWeekdays() {
const firstDayOfWeek = this._dateAdapter.getFirstDayOfWeek();
Expand Down
1 change: 0 additions & 1 deletion src/material/datepicker/multi-year-view.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
[cellAspectRatio]="4 / 7"
[activeCell]="_getActiveCell()"
(selectedValueChange)="_yearSelected($event)"
(activeDateChange)="_updateActiveDate($event)"
(keyup)="_handleCalendarBodyKeyup($event)"
(keydown)="_handleCalendarBodyKeydown($event)">
</tbody>
Expand Down
30 changes: 1 addition & 29 deletions src/material/datepicker/multi-year-view.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {dispatchFakeEvent, dispatchKeyboardEvent} from '../../cdk/testing/privat
import {Component, ViewChild} from '@angular/core';
import {waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing';
import {MatNativeDateModule} from '@angular/material/core';
import {JAN, MAR} from '../testing';
import {JAN} from '../testing';
import {By} from '@angular/platform-browser';
import {MatCalendarBody} from './calendar-body';
import {MatMultiYearView, yearsPerPage, yearsPerRow} from './multi-year-view';
Expand Down Expand Up @@ -216,34 +216,6 @@ describe('MatMultiYearView', () => {

expect(calendarInstance.date).toEqual(new Date(2017 + yearsPerPage * 2, JAN, 1));
});

it('should go to the year that is focused', () => {
fixture.componentInstance.date = new Date(2017, MAR, 5);
fixture.detectChanges();
expect(calendarInstance.date).toEqual(new Date(2017, MAR, 5));

const year2022Cell = fixture.debugElement.nativeElement.querySelector(
'[data-mat-row="1"][data-mat-col="2"] button',
) as HTMLElement;

dispatchFakeEvent(year2022Cell, 'focus');
fixture.detectChanges();

expect(calendarInstance.date).toEqual(new Date(2022, MAR, 5));
});

it('should not call `.focus()` when the active date is focused', () => {
const year2017Cell = fixture.debugElement.nativeElement.querySelector(
'[data-mat-row="0"][data-mat-col="1"] button',
) as HTMLElement;
const focusSpy = (year2017Cell.focus = jasmine.createSpy('cellFocused'));

dispatchFakeEvent(year2017Cell, 'focus');
fixture.detectChanges();

expect(calendarInstance.date).toEqual(new Date(2017, JAN, 1));
expect(focusSpy).not.toHaveBeenCalled();
});
});
});
});
Expand Down
61 changes: 13 additions & 48 deletions src/material/datepicker/multi-year-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,31 +204,18 @@ export class MatMultiYearView<D> implements AfterContentInit, OnDestroy {
/** Handles when a new year is selected. */
_yearSelected(event: MatCalendarUserEvent<number>) {
const year = event.value;
const selectedYear = this._dateAdapter.createDate(year, 0, 1);
const selectedDate = this._getDateFromYear(year);

this.yearSelected.emit(selectedYear);
this.selectedChange.emit(selectedDate);
}

/**
* Takes the index of a calendar body cell wrapped in in an event as argument. For the date that
* corresponds to the given cell, set `activeDate` to that date and fire `activeDateChange` with
* that date.
*
* This fucntion is used to match each component's model of the active date with the calendar
* body cell that was focused. It updates its value of `activeDate` synchronously and updates the
* parent's value asynchonously via the `activeDateChange` event. The child component receives an
* updated value asynchronously via the `activeCell` Input.
*/
_updateActiveDate(event: MatCalendarUserEvent<number>) {
const year = event.value;
const oldActiveDate = this._activeDate;

this.activeDate = this._getDateFromYear(year);
if (this._dateAdapter.compareDate(oldActiveDate, this.activeDate)) {
this.activeDateChange.emit(this.activeDate);
}
this.yearSelected.emit(this._dateAdapter.createDate(year, 0, 1));
let month = this._dateAdapter.getMonth(this.activeDate);
let daysInMonth = this._dateAdapter.getNumDaysInMonth(
this._dateAdapter.createDate(year, month, 1),
);
this.selectedChange.emit(
this._dateAdapter.createDate(
year,
month,
Math.min(this._dateAdapter.getDate(this.activeDate), daysInMonth),
),
);
}

/** Handles keydown events on the calendar body when calendar is in multi-year view. */
Expand Down Expand Up @@ -291,7 +278,7 @@ export class MatMultiYearView<D> implements AfterContentInit, OnDestroy {
this.activeDateChange.emit(this.activeDate);
}

this._focusActiveCellAfterViewChecked();
this._focusActiveCell();
// Prevent unexpected default actions such as form submission.
event.preventDefault();
}
Expand All @@ -316,28 +303,6 @@ export class MatMultiYearView<D> implements AfterContentInit, OnDestroy {
this._matCalendarBody._focusActiveCell();
}

/** Focuses the active cell after change detection has run and the microtask queue is empty. */
_focusActiveCellAfterViewChecked() {
this._matCalendarBody._scheduleFocusActiveCellAfterViewChecked();
}

/**
* Takes a year and returns a new date on the same day and month as the currently active date
* The returned date will have the same year as the argument date.
*/
private _getDateFromYear(year: number) {
const activeMonth = this._dateAdapter.getMonth(this.activeDate);
const daysInMonth = this._dateAdapter.getNumDaysInMonth(
this._dateAdapter.createDate(year, activeMonth, 1),
);
const normalizedDate = this._dateAdapter.createDate(
year,
activeMonth,
Math.min(this._dateAdapter.getDate(this.activeDate), daysInMonth),
);
return normalizedDate;
}

/** Creates an MatCalendarCell for the given year. */
private _createCellForYear(year: number) {
const date = this._dateAdapter.createDate(year, 0, 1);
Expand Down
1 change: 0 additions & 1 deletion src/material/datepicker/year-view.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
[cellAspectRatio]="4 / 7"
[activeCell]="_dateAdapter.getMonth(activeDate)"
(selectedValueChange)="_monthSelected($event)"
(activeDateChange)="_updateActiveDate($event)"
(keyup)="_handleCalendarBodyKeyup($event)"
(keydown)="_handleCalendarBodyKeydown($event)">
</tbody>
Expand Down
24 changes: 0 additions & 24 deletions src/material/datepicker/year-view.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,30 +292,6 @@ describe('MatYearView', () => {

expect(calendarInstance.date).toEqual(new Date(2018, FEB, 28));
});

it('should go to date that is focused', () => {
const juneCell = fixture.debugElement.nativeElement.querySelector(
'[data-mat-row="1"][data-mat-col="1"] button',
) as HTMLElement;

dispatchFakeEvent(juneCell, 'focus');
fixture.detectChanges();

expect(calendarInstance.date).toEqual(new Date(2017, JUN, 5));
});

it('should not call `.focus()` when the active date is focused', () => {
const janCell = fixture.debugElement.nativeElement.querySelector(
'[data-mat-row="0"][data-mat-col="0"] button',
) as HTMLElement;
const focusSpy = (janCell.focus = jasmine.createSpy('cellFocused'));

dispatchFakeEvent(janCell, 'focus');
fixture.detectChanges();

expect(calendarInstance.date).toEqual(new Date(2017, JAN, 5));
expect(focusSpy).not.toHaveBeenCalled();
});
});
});
});
Expand Down
Loading

0 comments on commit 60abc41

Please sign in to comment.