diff --git a/src/material/datepicker/calendar-body.html b/src/material/datepicker/calendar-body.html index 318516d5f626..ef944f636dff 100644 --- a/src/material/datepicker/calendar-body.html +++ b/src/material/datepicker/calendar-body.html @@ -14,7 +14,7 @@ } -@for (row of rows; track row; let rowIndex = $index) { +@for (row of rows; track _trackRow(row); let rowIndex = $index) { - @for (item of row; track item; let colIndex = $index) { + @for (item of row; track item.id; let colIndex = $index) { = ( view: 'month' | 'year' | 'multi-year', ) => MatCalendarCellCssClasses; +let uniqueIdCounter = 0; + /** * An internal class that represents the data corresponding to a single calendar cell. * @docs-private */ export class MatCalendarCell { + readonly id = uniqueIdCounter++; + constructor( public value: number, public displayValue: string, @@ -192,6 +196,13 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterView private _injector = inject(Injector); + /** + * Tracking function for rows based on their identity. Ideally we would use some sort of + * key on the row, but that would require a breaking change for the `rows` input. We don't + * use the built-in identity tracking, because it logs warnings. + */ + _trackRow = (row: MatCalendarCell[]) => row; + constructor( private _elementRef: ElementRef, private _ngZone: NgZone, diff --git a/src/material/datepicker/month-view.html b/src/material/datepicker/month-view.html index e292c7152b41..538d85f91435 100644 --- a/src/material/datepicker/month-view.html +++ b/src/material/datepicker/month-view.html @@ -1,7 +1,7 @@ - @for (day of _weekdays; track day) { + @for (day of _weekdays; track day.id) {
{{day.long}} diff --git a/src/material/datepicker/month-view.ts b/src/material/datepicker/month-view.ts index 1937e75c04ad..ee92ef19bdf5 100644 --- a/src/material/datepicker/month-view.ts +++ b/src/material/datepicker/month-view.ts @@ -55,6 +55,8 @@ import { const DAYS_PER_WEEK = 7; +let uniqueIdCounter = 0; + /** * An internal component used to display a single month in the datepicker. * @docs-private @@ -206,7 +208,7 @@ export class MatMonthView implements AfterContentInit, OnChanges, OnDestroy { _todayDate: number | null; /** The names of the weekdays. */ - _weekdays: {long: string; narrow: string}[]; + _weekdays: {long: string; narrow: string; id: number}[]; constructor( readonly _changeDetectorRef: ChangeDetectorRef, @@ -508,7 +510,7 @@ export class MatMonthView implements AfterContentInit, OnChanges, OnDestroy { // Rotate the labels for days of the week based on the configured first day of the week. let weekdays = longWeekdays.map((long, i) => { - return {long, narrow: narrowWeekdays[i]}; + return {long, narrow: narrowWeekdays[i], id: uniqueIdCounter++}; }); this._weekdays = weekdays.slice(firstDayOfWeek).concat(weekdays.slice(0, firstDayOfWeek)); } diff --git a/tools/public_api_guard/material/datepicker.md b/tools/public_api_guard/material/datepicker.md index a054065a2c93..08b0d2f9ab0b 100644 --- a/tools/public_api_guard/material/datepicker.md +++ b/tools/public_api_guard/material/datepicker.md @@ -248,6 +248,7 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterView _startDateLabelId: string; startValue: number; todayValue: number; + _trackRow: (row: MatCalendarCell[]) => MatCalendarCell[]; // (undocumented) static ɵcmp: i0.ɵɵComponentDeclaration, "[mat-calendar-body]", ["matCalendarBody"], { "label": { "alias": "label"; "required": false; }; "rows": { "alias": "rows"; "required": false; }; "todayValue": { "alias": "todayValue"; "required": false; }; "startValue": { "alias": "startValue"; "required": false; }; "endValue": { "alias": "endValue"; "required": false; }; "labelMinRequiredCells": { "alias": "labelMinRequiredCells"; "required": false; }; "numCols": { "alias": "numCols"; "required": false; }; "activeCell": { "alias": "activeCell"; "required": false; }; "isRange": { "alias": "isRange"; "required": false; }; "cellAspectRatio": { "alias": "cellAspectRatio"; "required": false; }; "comparisonStart": { "alias": "comparisonStart"; "required": false; }; "comparisonEnd": { "alias": "comparisonEnd"; "required": false; }; "previewStart": { "alias": "previewStart"; "required": false; }; "previewEnd": { "alias": "previewEnd"; "required": false; }; "startDateAccessibleName": { "alias": "startDateAccessibleName"; "required": false; }; "endDateAccessibleName": { "alias": "endDateAccessibleName"; "required": false; }; }, { "selectedValueChange": "selectedValueChange"; "previewChange": "previewChange"; "activeDateChange": "activeDateChange"; "dragStarted": "dragStarted"; "dragEnded": "dragEnded"; }, never, never, true, never>; // (undocumented) @@ -268,6 +269,8 @@ export class MatCalendarCell { // (undocumented) enabled: boolean; // (undocumented) + readonly id: number; + // (undocumented) rawValue?: D | undefined; // (undocumented) value: number; @@ -748,6 +751,7 @@ export class MatMonthView implements AfterContentInit, OnChanges, OnDestroy { _weekdays: { long: string; narrow: string; + id: number; }[]; _weeks: MatCalendarCell[][]; // (undocumented)