diff --git a/.gitignore b/.gitignore
index ce0991dfb3e0..2a71b14567d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,8 @@ node_modules
/.vs
*.swo
*.swp
+.vimrc
+.nvimrc
# misc
.DS_Store
diff --git a/src/material/datepicker/calendar-body.html b/src/material/datepicker/calendar-body.html
index ffdfef27c1cd..d0c1f7870611 100644
--- a/src/material/datepicker/calendar-body.html
+++ b/src/material/datepicker/calendar-body.html
@@ -26,40 +26,59 @@
[style.paddingBottom]="_cellPadding">
{{_firstRowOffset >= labelMinRequiredCells ? label : ''}}
-
-
- {{item.displayValue}}
+
+
+
+
+ {{item.displayValue}}
+
+
+
|
diff --git a/src/material/datepicker/calendar-body.scss b/src/material/datepicker/calendar-body.scss
index c2d2f78df048..d77f2fc4377c 100644
--- a/src/material/datepicker/calendar-body.scss
+++ b/src/material/datepicker/calendar-body.scss
@@ -31,7 +31,12 @@ $calendar-range-end-body-cell-size:
padding-right: $calendar-body-label-side-padding;
}
+.mat-calendar-body-cell-wrapper {
+ display: contents;
+}
+
.mat-calendar-body-cell {
+ display: table-cell;
position: relative;
height: 0;
line-height: 0;
diff --git a/src/material/datepicker/calendar-body.ts b/src/material/datepicker/calendar-body.ts
index 895db4b41472..ecb25003ee8f 100644
--- a/src/material/datepicker/calendar-body.ts
+++ b/src/material/datepicker/calendar-body.ts
@@ -122,6 +122,9 @@ export class MatCalendarBody implements OnChanges, OnDestroy {
/** Emits when a new value is selected. */
@Output() readonly selectedValueChange = new EventEmitter >();
+ /** Emits when a new date becomes active. */
+ @Output() readonly activeValueChange = new EventEmitter>();
+
/** Emits when the preview has changed as a result of a user action. */
@Output() readonly previewChange = new EventEmitter<
MatCalendarUserEvent
@@ -153,6 +156,13 @@ export class MatCalendarBody implements OnChanges, OnDestroy {
}
}
+ /** Called when a cell is focused. */
+ _cellFocused(cell: MatCalendarCell, event: any): void {
+ if (cell.enabled) {
+ this.activeValueChange.emit({value: cell.value, event});
+ }
+ }
+
/** Returns whether a cell should be marked as selected. */
_isSelected(value: number) {
return this.startValue === value || this.endValue === value;
@@ -337,7 +347,11 @@ export class MatCalendarBody implements OnChanges, OnDestroy {
// Only reset the preview end value when leaving cells. This looks better, because
// we have a gap between the cells and the rows and we don't want to remove the
// range just for it to show up again when the user moves a few pixels to the side.
- if (event.target && isTableCell(event.target as HTMLElement)) {
+ if (
+ event.target &&
+ (event.target as HTMLElement).parentElement &&
+ isTableCell((event.target as HTMLElement).parentElement as HTMLElement)
+ ) {
this._ngZone.run(() => this.previewChange.emit({value: null, event}));
}
}
@@ -350,7 +364,7 @@ export class MatCalendarBody implements OnChanges, OnDestroy {
if (isTableCell(element)) {
cell = element;
} else if (isTableCell(element.parentNode!)) {
- cell = element.parentNode as HTMLElement;
+ cell = element;
}
if (cell) {
diff --git a/src/material/datepicker/month-view.html b/src/material/datepicker/month-view.html
index 35deaf2339c2..e3c5440d9ff3 100644
--- a/src/material/datepicker/month-view.html
+++ b/src/material/datepicker/month-view.html
@@ -24,6 +24,7 @@
[labelMinRequiredCells]="3"
[activeCell]="_dateAdapter.getDate(activeDate) - 1"
(selectedValueChange)="_dateSelected($event)"
+ (activeValueChange)="_dayBecomesActive($event)"
(previewChange)="_previewChanged($event)"
(keyup)="_handleCalendarBodyKeyup($event)"
(keydown)="_handleCalendarBodyKeydown($event)">
diff --git a/src/material/datepicker/month-view.spec.ts b/src/material/datepicker/month-view.spec.ts
index 7a4909f8efbb..a769a80c67ec 100644
--- a/src/material/datepicker/month-view.spec.ts
+++ b/src/material/datepicker/month-view.spec.ts
@@ -149,13 +149,14 @@ describe('MatMonthView', () => {
fixture.detectChanges();
});
- it('should decrement date on left arrow press', () => {
+ fit('should decrement date on left arrow press', () => {
dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW);
fixture.detectChanges();
expect(calendarInstance.date).toEqual(new Date(2017, JAN, 4));
calendarInstance.date = new Date(2017, JAN, 1);
fixture.detectChanges();
+ expect(calendarInstance.date).toEqual(new Date(2017, JAN, 1));
dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW);
fixture.detectChanges();
@@ -653,7 +654,16 @@ describe('MatMonthView', () => {
(_userSelection)="userSelectionSpy($event)">`,
})
class StandardMonthView {
- date = new Date(2017, JAN, 5);
+ get date(): Date {
+ console.log('test code. `get date`', this._date);
+ return this._date;
+ }
+ set date(date: Date) {
+ console.log('test code. `set date`', date);
+ this._date = date;
+ }
+ _date = new Date(2017, JAN, 5);
+
selected: Date | DateRange = new Date(2017, JAN, 10);
selectedChangeSpy = jasmine.createSpy('selectedChange');
userSelectionSpy = jasmine.createSpy('userSelection');
diff --git a/src/material/datepicker/month-view.ts b/src/material/datepicker/month-view.ts
index a46abfb4dfbd..bece84601f4f 100644
--- a/src/material/datepicker/month-view.ts
+++ b/src/material/datepicker/month-view.ts
@@ -252,6 +252,30 @@ export class MatMonthView implements AfterContentInit, OnChanges, OnDestroy {
this._changeDetectorRef.markForCheck();
}
+ _dayBecomesActive(event: MatCalendarUserEvent) {
+ const date = event.value;
+ const selectedYear = this._dateAdapter.getYear(this.activeDate);
+ const selectedMonth = this._dateAdapter.getMonth(this.activeDate);
+ const activeDate = this._dateAdapter.createDate(selectedYear, selectedMonth, date);
+ let rangeStartDate: number | null;
+ let rangeEndDate: number | null;
+
+ if (this._activeDate instanceof DateRange) {
+ rangeStartDate = this._getDateInCurrentMonth(this._activeDate.start);
+ rangeEndDate = this._getDateInCurrentMonth(this._activeDate.end);
+ } else {
+ rangeStartDate = rangeEndDate = this._getDateInCurrentMonth(this._activeDate);
+ }
+
+ this.activeDate = activeDate;
+
+ if (rangeStartDate !== date || rangeEndDate !== date) {
+ this.activeDateChange.emit(activeDate);
+ }
+
+ this._changeDetectorRef.markForCheck();
+ }
+
/** 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
@@ -326,10 +350,12 @@ export class MatMonthView implements AfterContentInit, OnChanges, OnDestroy {
}
if (this._dateAdapter.compareDate(oldActiveDate, this.activeDate)) {
+ console.log("firing activeDateChange", this.activeDate);
this.activeDateChange.emit(this.activeDate);
}
this._focusActiveCell();
+
// Prevent unexpected default actions such as form submission.
event.preventDefault();
}
diff --git a/src/material/datepicker/multi-year-view.html b/src/material/datepicker/multi-year-view.html
index ee12a9e67d29..da2de1cf26e4 100644
--- a/src/material/datepicker/multi-year-view.html
+++ b/src/material/datepicker/multi-year-view.html
@@ -11,6 +11,7 @@
[cellAspectRatio]="4 / 7"
[activeCell]="_getActiveCell()"
(selectedValueChange)="_yearSelected($event)"
+ (activeValueChange)="_yearBecomesActive($event)"
(keyup)="_handleCalendarBodyKeyup($event)"
(keydown)="_handleCalendarBodyKeydown($event)">
diff --git a/src/material/datepicker/multi-year-view.ts b/src/material/datepicker/multi-year-view.ts
index da7206057bdc..c11e58e08f54 100644
--- a/src/material/datepicker/multi-year-view.ts
+++ b/src/material/datepicker/multi-year-view.ts
@@ -218,6 +218,21 @@ export class MatMultiYearView implements AfterContentInit, OnDestroy {
);
}
+ _yearBecomesActive(event: MatCalendarUserEvent) {
+ const year = event.value;
+ let month = this._dateAdapter.getMonth(this.activeDate);
+ let daysInMonth = this._dateAdapter.getNumDaysInMonth(
+ this._dateAdapter.createDate(year, month, 1),
+ );
+ this.activeDateChange.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. */
_handleCalendarBodyKeydown(event: KeyboardEvent): void {
const oldActiveDate = this._activeDate;
@@ -278,7 +293,6 @@ export class MatMultiYearView implements AfterContentInit, OnDestroy {
this.activeDateChange.emit(this.activeDate);
}
- this._focusActiveCell();
// Prevent unexpected default actions such as form submission.
event.preventDefault();
}
diff --git a/src/material/datepicker/year-view.html b/src/material/datepicker/year-view.html
index dae81c5e2a27..c54b0c71269d 100644
--- a/src/material/datepicker/year-view.html
+++ b/src/material/datepicker/year-view.html
@@ -13,6 +13,7 @@
[cellAspectRatio]="4 / 7"
[activeCell]="_dateAdapter.getMonth(activeDate)"
(selectedValueChange)="_monthSelected($event)"
+ (activeValueChange)="_monthBecomesActive($event)"
(keyup)="_handleCalendarBodyKeyup($event)"
(keydown)="_handleCalendarBodyKeydown($event)">
diff --git a/src/material/datepicker/year-view.ts b/src/material/datepicker/year-view.ts
index 2e121f75cc15..c7931e1acac0 100644
--- a/src/material/datepicker/year-view.ts
+++ b/src/material/datepicker/year-view.ts
@@ -198,6 +198,25 @@ export class MatYearView implements AfterContentInit, OnDestroy {
);
}
+ /** Handles when a new month becomes active. */
+ _monthBecomesActive(event: MatCalendarUserEvent) {
+ const month = event.value;
+ const normalizedDate = this._dateAdapter.createDate(
+ this._dateAdapter.getYear(this.activeDate),
+ month,
+ 1,
+ );
+
+ const daysInMonth = this._dateAdapter.getNumDaysInMonth(normalizedDate);
+
+ this.activeDateChange.emit(
+ this._dateAdapter.createDate(
+ this._dateAdapter.getYear(this.activeDate),
+ month,
+ Math.min(this._dateAdapter.getDate(this.activeDate), daysInMonth),
+ ),
+ );
+ }
/** Handles keydown events on the calendar body when calendar is in year view. */
_handleCalendarBodyKeydown(event: KeyboardEvent): void {
// TODO(mmalerba): We currently allow keyboard navigation to disabled dates, but just prevent
@@ -261,7 +280,6 @@ export class MatYearView implements AfterContentInit, OnDestroy {
this.activeDateChange.emit(this.activeDate);
}
- this._focusActiveCell();
// Prevent unexpected default actions such as form submission.
event.preventDefault();
}
|