Skip to content
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
40 changes: 20 additions & 20 deletions goldens/material/datepicker/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -667,8 +667,8 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
// (undocumented)
readonly _changeDetectorRef: ChangeDetectorRef;
comparisonEnd: D | null;
_comparisonRangeEnd: number | null;
_comparisonRangeStart: number | null;
_comparisonRangeEnd: i0.WritableSignal<number | null>;
_comparisonRangeStart: i0.WritableSignal<number | null>;
comparisonStart: D | null;
// (undocumented)
_dateAdapter: DateAdapter<D, any>;
Expand All @@ -679,43 +679,43 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
protected _dragEnded(event: MatCalendarUserEvent<D | null>): void;
readonly dragStarted: EventEmitter<MatCalendarUserEvent<D>>;
endDateAccessibleName: string | null;
_firstWeekOffset: number;
_firstWeekOffset: i0.WritableSignal<number>;
_focusActiveCell(movePreview?: boolean): void;
_focusActiveCellAfterViewChecked(): void;
_handleCalendarBodyKeydown(event: KeyboardEvent): void;
_handleCalendarBodyKeyup(event: KeyboardEvent): void;
_init(): void;
_isRange: boolean;
_isRange: i0.WritableSignal<boolean>;
_matCalendarBody: MatCalendarBody;
get maxDate(): D | null;
set maxDate(value: D | null);
get minDate(): D | null;
set minDate(value: D | null);
_monthLabel: string;
_monthLabel: i0.WritableSignal<string>;
// (undocumented)
ngAfterContentInit(): void;
// (undocumented)
ngOnChanges(changes: SimpleChanges): void;
// (undocumented)
ngOnDestroy(): void;
_previewChanged({ event, value: cell }: MatCalendarUserEvent<MatCalendarCell<D> | null>): void;
_previewEnd: number | null;
_previewStart: number | null;
_rangeEnd: number | null;
_rangeStart: number | null;
_previewEnd: i0.WritableSignal<number | null>;
_previewStart: i0.WritableSignal<number | null>;
_rangeEnd: i0.WritableSignal<number | null>;
_rangeStart: i0.WritableSignal<number | null>;
get selected(): DateRange<D> | D | null;
set selected(value: DateRange<D> | D | null);
readonly selectedChange: EventEmitter<D | null>;
startDateAccessibleName: string | null;
_todayDate: number | null;
_todayDate: i0.WritableSignal<number | null>;
_updateActiveDate(event: MatCalendarUserEvent<number>): void;
readonly _userSelection: EventEmitter<MatCalendarUserEvent<D | null>>;
_weekdays: {
_weekdays: i0.WritableSignal<{
long: string;
narrow: string;
id: number;
}[];
_weeks: MatCalendarCell[][];
}[]>;
_weeks: i0.WritableSignal<MatCalendarCell<any>[][]>;
// (undocumented)
static ɵcmp: i0.ɵɵComponentDeclaration<MatMonthView<any>, "mat-month-view", ["matMonthView"], { "activeDate": { "alias": "activeDate"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "minDate": { "alias": "minDate"; "required": false; }; "maxDate": { "alias": "maxDate"; "required": false; }; "dateFilter": { "alias": "dateFilter"; "required": false; }; "dateClass": { "alias": "dateClass"; "required": false; }; "comparisonStart": { "alias": "comparisonStart"; "required": false; }; "comparisonEnd": { "alias": "comparisonEnd"; "required": false; }; "startDateAccessibleName": { "alias": "startDateAccessibleName"; "required": false; }; "endDateAccessibleName": { "alias": "endDateAccessibleName"; "required": false; }; "activeDrag": { "alias": "activeDrag"; "required": false; }; }, { "selectedChange": "selectedChange"; "_userSelection": "_userSelection"; "dragStarted": "dragStarted"; "dragEnded": "dragEnded"; "activeDateChange": "activeDateChange"; }, never, never, true, never>;
// (undocumented)
Expand Down Expand Up @@ -751,10 +751,10 @@ export class MatMultiYearView<D> implements AfterContentInit, OnDestroy {
get selected(): DateRange<D> | D | null;
set selected(value: DateRange<D> | D | null);
readonly selectedChange: EventEmitter<D>;
_selectedYear: number | null;
_todayYear: number;
_selectedYear: i0.WritableSignal<number | null>;
_todayYear: i0.WritableSignal<number>;
_updateActiveDate(event: MatCalendarUserEvent<number>): void;
_years: MatCalendarCell[][];
_years: i0.WritableSignal<MatCalendarCell<any>[][]>;
readonly yearSelected: EventEmitter<D>;
_yearSelected(event: MatCalendarUserEvent<number>): void;
// (undocumented)
Expand Down Expand Up @@ -831,7 +831,7 @@ export class MatYearView<D> implements AfterContentInit, OnDestroy {
set maxDate(value: D | null);
get minDate(): D | null;
set minDate(value: D | null);
_months: MatCalendarCell[][];
_months: i0.WritableSignal<MatCalendarCell<any>[][]>;
readonly monthSelected: EventEmitter<D>;
_monthSelected(event: MatCalendarUserEvent<number>): void;
// (undocumented)
Expand All @@ -841,10 +841,10 @@ export class MatYearView<D> implements AfterContentInit, OnDestroy {
get selected(): DateRange<D> | D | null;
set selected(value: DateRange<D> | D | null);
readonly selectedChange: EventEmitter<D>;
_selectedMonth: number | null;
_todayMonth: number | null;
_selectedMonth: i0.WritableSignal<number | null>;
_todayMonth: i0.WritableSignal<number | null>;
_updateActiveDate(event: MatCalendarUserEvent<number>): void;
_yearLabel: string;
_yearLabel: i0.WritableSignal<string>;
// (undocumented)
static ɵcmp: i0.ɵɵComponentDeclaration<MatYearView<any>, "mat-year-view", ["matYearView"], { "activeDate": { "alias": "activeDate"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "minDate": { "alias": "minDate"; "required": false; }; "maxDate": { "alias": "maxDate"; "required": false; }; "dateFilter": { "alias": "dateFilter"; "required": false; }; "dateClass": { "alias": "dateClass"; "required": false; }; }, { "selectedChange": "selectedChange"; "monthSelected": "monthSelected"; "activeDateChange": "activeDateChange"; }, never, never, true, never>;
// (undocumented)
Expand Down
4 changes: 3 additions & 1 deletion src/material/datepicker/calendar-body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,9 @@ export class MatCalendarBody<D = any> implements OnChanges, OnDestroy, AfterView
const col = cell.getAttribute('data-mat-col');

if (row && col) {
return this.rows[parseInt(row)][parseInt(col)];
// We need the optional read here, because this can
// fire too late when the user is navigating quickly.
return this.rows[parseInt(row)]?.[parseInt(col)] || null;
}
}

Expand Down
22 changes: 11 additions & 11 deletions src/material/datepicker/month-view.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<table class="mat-calendar-table" role="grid">
<thead class="mat-calendar-table-header">
<tr>
@for (day of _weekdays; track day.id) {
@for (day of _weekdays(); track day.id) {
<th scope="col">
<span class="cdk-visually-hidden">{{day.long}}</span>
<span aria-hidden="true">{{day.narrow}}</span>
Expand All @@ -11,16 +11,16 @@
<tr aria-hidden="true"><th class="mat-calendar-table-header-divider" colspan="7"></th></tr>
</thead>
<tbody mat-calendar-body
[label]="_monthLabel"
[rows]="_weeks"
[todayValue]="_todayDate!"
[startValue]="_rangeStart!"
[endValue]="_rangeEnd!"
[comparisonStart]="_comparisonRangeStart"
[comparisonEnd]="_comparisonRangeEnd"
[previewStart]="_previewStart"
[previewEnd]="_previewEnd"
[isRange]="_isRange"
[label]="_monthLabel()"
[rows]="_weeks()"
[todayValue]="_todayDate()!"
[startValue]="_rangeStart()!"
[endValue]="_rangeEnd()!"
[comparisonStart]="_comparisonRangeStart()"
[comparisonEnd]="_comparisonRangeEnd()"
[previewStart]="_previewStart()"
[previewEnd]="_previewEnd()"
[isRange]="_isRange()"
[labelMinRequiredCells]="3"
[activeCell]="_dateAdapter.getDate(activeDate) - 1"
[startDateAccessibleName]="startDateAccessibleName"
Expand Down
91 changes: 46 additions & 45 deletions src/material/datepicker/month-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
SimpleChanges,
OnChanges,
inject,
signal,
} from '@angular/core';
import {DateAdapter, MAT_DATE_FORMATS, MatDateFormats} from '../core';
import {Directionality} from '@angular/cdk/bidi';
Expand Down Expand Up @@ -183,40 +184,40 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
@ViewChild(MatCalendarBody) _matCalendarBody: MatCalendarBody;

/** The label for this month (e.g. "January 2017"). */
_monthLabel: string;
_monthLabel = signal('');

/** Grid of calendar cells representing the dates of the month. */
_weeks: MatCalendarCell[][];
_weeks = signal<MatCalendarCell[][]>([]);

/** The number of blank cells in the first row before the 1st of the month. */
_firstWeekOffset: number;
_firstWeekOffset = signal(0);

/** Start value of the currently-shown date range. */
_rangeStart: number | null;
_rangeStart = signal<number | null>(null);

/** End value of the currently-shown date range. */
_rangeEnd: number | null;
_rangeEnd = signal<number | null>(null);

/** Start value of the currently-shown comparison date range. */
_comparisonRangeStart: number | null;
_comparisonRangeStart = signal<number | null>(null);

/** End value of the currently-shown comparison date range. */
_comparisonRangeEnd: number | null;
_comparisonRangeEnd = signal<number | null>(null);

/** Start of the preview range. */
_previewStart: number | null;
_previewStart = signal<number | null>(null);

/** End of the preview range. */
_previewEnd: number | null;
_previewEnd = signal<number | null>(null);

/** Whether the user is currently selecting a range of dates. */
_isRange: boolean;
_isRange = signal(false);

/** The date of the month that today falls on. Null if today is in another month. */
_todayDate: number | null;
_todayDate = signal<number | null>(null);

/** The names of the weekdays. */
_weekdays: {long: string; narrow: string; id: number}[];
_weekdays = signal<{long: string; narrow: string; id: number}[]>([]);

constructor(...args: unknown[]);

Expand Down Expand Up @@ -359,7 +360,7 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
return;
case ESCAPE:
// Abort the current range selection if the user presses escape mid-selection.
if (this._previewEnd != null && !hasModifierKey(event)) {
if (this._previewEnd() != null && !hasModifierKey(event)) {
this._clearPreview();
// If a drag is in progress, cancel the drag without changing the
// current selection.
Expand Down Expand Up @@ -402,23 +403,26 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
/** Initializes this month view. */
_init() {
this._setRanges(this.selected);
this._todayDate = this._getCellCompareValue(this._dateAdapter.today());
this._monthLabel = this._dateFormats.display.monthLabel
? this._dateAdapter.format(this.activeDate, this._dateFormats.display.monthLabel)
: this._dateAdapter
.getMonthNames('short')
[this._dateAdapter.getMonth(this.activeDate)].toLocaleUpperCase();
this._todayDate.set(this._getCellCompareValue(this._dateAdapter.today()));
this._monthLabel.set(
this._dateFormats.display.monthLabel
? this._dateAdapter.format(this.activeDate, this._dateFormats.display.monthLabel)
: this._dateAdapter
.getMonthNames('short')
[this._dateAdapter.getMonth(this.activeDate)].toLocaleUpperCase(),
);

let firstOfMonth = this._dateAdapter.createDate(
this._dateAdapter.getYear(this.activeDate),
this._dateAdapter.getMonth(this.activeDate),
1,
);
this._firstWeekOffset =
this._firstWeekOffset.set(
(DAYS_PER_WEEK +
this._dateAdapter.getDayOfWeek(firstOfMonth) -
this._dateAdapter.getFirstDayOfWeek()) %
DAYS_PER_WEEK;
DAYS_PER_WEEK,
);

this._initWeekdays();
this._createWeekCells();
Expand Down Expand Up @@ -446,8 +450,8 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
this.selected as DateRange<D>,
event,
);
this._previewStart = this._getCellCompareValue(previewRange.start);
this._previewEnd = this._getCellCompareValue(previewRange.end);
this._previewStart.set(this._getCellCompareValue(previewRange.start));
this._previewEnd.set(this._getCellCompareValue(previewRange.end));

if (this.activeDrag && value) {
const dragRange = this._rangeStrategy.createDrag?.(
Expand All @@ -458,16 +462,10 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
);

if (dragRange) {
this._previewStart = this._getCellCompareValue(dragRange.start);
this._previewEnd = this._getCellCompareValue(dragRange.end);
this._previewStart.set(this._getCellCompareValue(dragRange.start));
this._previewEnd.set(this._getCellCompareValue(dragRange.end));
}
}

// Note that here we need to use `detectChanges`, rather than `markForCheck`, because
// the way `_focusActiveCell` is set up at the moment makes it fire at the wrong time
// when navigating one month back using the keyboard which will cause this handler
// to throw a "changed after checked" error when updating the preview state.
this._changeDetectorRef.detectChanges();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleting this line is the fix for #31959.

}
}

Expand Down Expand Up @@ -512,20 +510,20 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
const longWeekdays = this._dateAdapter.getDayOfWeekNames('long');

// Rotate the labels for days of the week based on the configured first day of the week.
let weekdays = longWeekdays.map((long, i) => {
const weekdays = longWeekdays.map((long, i) => {
return {long, narrow: narrowWeekdays[i], id: uniqueIdCounter++};
});
this._weekdays = weekdays.slice(firstDayOfWeek).concat(weekdays.slice(0, firstDayOfWeek));
this._weekdays.set(weekdays.slice(firstDayOfWeek).concat(weekdays.slice(0, firstDayOfWeek)));
}

/** Creates MatCalendarCells for the dates in this month. */
private _createWeekCells() {
const daysInMonth = this._dateAdapter.getNumDaysInMonth(this.activeDate);
const dateNames = this._dateAdapter.getDateNames();
this._weeks = [[]];
for (let i = 0, cell = this._firstWeekOffset; i < daysInMonth; i++, cell++) {
const weeks: MatCalendarCell[][] = [[]];
for (let i = 0, cell = this._firstWeekOffset(); i < daysInMonth; i++, cell++) {
if (cell == DAYS_PER_WEEK) {
this._weeks.push([]);
weeks.push([]);
cell = 0;
}
const date = this._dateAdapter.createDate(
Expand All @@ -537,7 +535,7 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
const ariaLabel = this._dateAdapter.format(date, this._dateFormats.display.dateA11yLabel);
const cellClasses = this.dateClass ? this.dateClass(date, 'month') : undefined;

this._weeks[this._weeks.length - 1].push(
weeks[weeks.length - 1].push(
new MatCalendarCell<D>(
i + 1,
dateNames[i],
Expand All @@ -549,6 +547,7 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
),
);
}
this._weeks.set(weeks);
}

/** Date filter for the month */
Expand Down Expand Up @@ -603,16 +602,17 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {
/** Sets the current range based on a model value. */
private _setRanges(selectedValue: DateRange<D> | D | null) {
if (selectedValue instanceof DateRange) {
this._rangeStart = this._getCellCompareValue(selectedValue.start);
this._rangeEnd = this._getCellCompareValue(selectedValue.end);
this._isRange = true;
this._rangeStart.set(this._getCellCompareValue(selectedValue.start));
this._rangeEnd.set(this._getCellCompareValue(selectedValue.end));
this._isRange.set(true);
} else {
this._rangeStart = this._rangeEnd = this._getCellCompareValue(selectedValue);
this._isRange = false;
this._rangeStart.set(this._getCellCompareValue(selectedValue));
this._rangeEnd.set(this._rangeStart());
this._isRange.set(false);
}

this._comparisonRangeStart = this._getCellCompareValue(this.comparisonStart);
this._comparisonRangeEnd = this._getCellCompareValue(this.comparisonEnd);
this._comparisonRangeStart.set(this._getCellCompareValue(this.comparisonStart));
this._comparisonRangeEnd.set(this._getCellCompareValue(this.comparisonEnd));
}

/** Gets whether a date can be selected in the month view. */
Expand All @@ -622,6 +622,7 @@ export class MatMonthView<D> implements AfterContentInit, OnChanges, OnDestroy {

/** Clears out preview state. */
private _clearPreview() {
this._previewStart = this._previewEnd = null;
this._previewStart.set(null);
this._previewEnd.set(null);
}
}
8 changes: 4 additions & 4 deletions src/material/datepicker/multi-year-view.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
<tr><th class="mat-calendar-table-header-divider" colspan="4"></th></tr>
</thead>
<tbody mat-calendar-body
[rows]="_years"
[todayValue]="_todayYear"
[startValue]="_selectedYear!"
[endValue]="_selectedYear!"
[rows]="_years()"
[todayValue]="_todayYear()"
[startValue]="_selectedYear()!"
[endValue]="_selectedYear()!"
[numCols]="4"
[cellAspectRatio]="4 / 7"
[activeCell]="_getActiveCell()"
Expand Down
Loading
Loading