diff --git a/package-lock.json b/package-lock.json index 4b4e96f77733..59ce0d3d8eda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11265,7 +11265,7 @@ "q": "1.5.1", "sauce-connect-launcher": "1.2.3", "saucelabs": "1.4.0", - "wd": "1.4.1" + "wd": "1.5.0" }, "dependencies": { "q": { @@ -18067,9 +18067,9 @@ "dev": true }, "wd": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/wd/-/wd-1.4.1.tgz", - "integrity": "sha512-C0wWd2X4SWWcyx5qxaixiZE4Vb07sl0yDfWHPeml8lDHSbmI9erE9BmTHIqOGoDxGgJ3/hkFmODQ7ZLKiF8+8Q==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/wd/-/wd-1.5.0.tgz", + "integrity": "sha512-e/KpzTlhtSG3Ek0AcRz4G6PhxGsc53Nro+GkI1er9p05tWQ7W9dpGZR5SqQzGUqvbaqJCThDSAGaY7LHgi6MiA==", "dev": true, "requires": { "archiver": "1.3.0", diff --git a/src/demo-app/datepicker/datepicker-demo.html b/src/demo-app/datepicker/datepicker-demo.html index e858a111b14b..4d428a549f79 100644 --- a/src/demo-app/datepicker/datepicker-demo.html +++ b/src/demo-app/datepicker/datepicker-demo.html @@ -90,7 +90,7 @@

Input disabled datepicker

[matDatepickerFilter]="filterOdd ? dateFilter : null" disabled placeholder="Input disabled"> + [startView]="yearView ? 'year' : 'month'">

@@ -118,7 +118,7 @@

Input disabled, datepicker popup enabled

[max]="maxDate" [matDatepickerFilter]="filterOdd ? dateFilter : null" placeholder="Input disabled, datepicker enabled"> + [startView]="yearView ? 'year' : 'month'">

diff --git a/src/demo-app/datepicker/datepicker-demo.scss b/src/demo-app/datepicker/datepicker-demo.scss index 9672ffb589e1..1dc57962c1c4 100644 --- a/src/demo-app/datepicker/datepicker-demo.scss +++ b/src/demo-app/datepicker/datepicker-demo.scss @@ -1,3 +1,4 @@ mat-calendar { width: 300px; } + diff --git a/src/demo-app/datepicker/datepicker-demo.ts b/src/demo-app/datepicker/datepicker-demo.ts index 8bdcc6f821d4..ae4c40758458 100644 --- a/src/demo-app/datepicker/datepicker-demo.ts +++ b/src/demo-app/datepicker/datepicker-demo.ts @@ -8,8 +8,7 @@ import {ChangeDetectionStrategy, Component} from '@angular/core'; import {FormControl} from '@angular/forms'; -import {MatDatepickerInputEvent} from '@angular/material/datepicker'; - +import {MatDatepickerInputEvent} from '@angular/material'; @Component({ moduleId: module.id, @@ -31,11 +30,11 @@ export class DatepickerDemo { lastDateInput: Date | null; lastDateChange: Date | null; + dateCtrl = new FormControl(); + dateFilter = (date: Date) => !(date.getFullYear() % 2) && (date.getMonth() % 2) && !(date.getDate() % 2) onDateInput = (e: MatDatepickerInputEvent) => this.lastDateInput = e.value; onDateChange = (e: MatDatepickerInputEvent) => this.lastDateChange = e.value; - - dateCtrl = new FormControl(); } diff --git a/src/demo-app/demo-app-module.ts b/src/demo-app/demo-app-module.ts index a60bcb9f2e4d..5e42bbf01d24 100644 --- a/src/demo-app/demo-app-module.ts +++ b/src/demo-app/demo-app-module.ts @@ -31,7 +31,7 @@ import {AccessibilityDemoModule} from './a11y/a11y-module'; ], entryComponents: [ EntryApp, - ], + ] }) export class DemoAppModule { constructor(private _appRef: ApplicationRef) { } diff --git a/src/lib/datepicker/calendar.html b/src/lib/datepicker/calendar.html index 594fc00e1d5d..7b06f3296eab 100644 --- a/src/lib/datepicker/calendar.html +++ b/src/lib/datepicker/calendar.html @@ -36,6 +36,7 @@ [activeDate]="_activeDate" [selected]="selected" [dateFilter]="_dateFilterForViews" + (monthSelected)="_monthSelectedInYearView($event)" (selectedChange)="_goToDateInView($event, 'month')"> @@ -44,6 +45,7 @@ [activeDate]="_activeDate" [selected]="selected" [dateFilter]="_dateFilterForViews" + (yearSelected)="_yearSelectedInMultiYearView($event)" (selectedChange)="_goToDateInView($event, 'year')"> diff --git a/src/lib/datepicker/calendar.spec.ts b/src/lib/datepicker/calendar.spec.ts index 24e331b50efc..2f8880eac2fb 100644 --- a/src/lib/datepicker/calendar.spec.ts +++ b/src/lib/datepicker/calendar.spec.ts @@ -196,6 +196,40 @@ describe('MatCalendar', () => { expect(testComponent.selected).toEqual(new Date(2017, JAN, 31)); }); + it('should emit the selected month on cell clicked in year view', () => { + periodButton.click(); + fixture.detectChanges(); + + expect(calendarInstance._currentView).toBe('multi-year'); + expect(calendarInstance._activeDate).toEqual(new Date(2017, JAN, 31)); + + (calendarElement.querySelector('.mat-calendar-body-active') as HTMLElement).click(); + + fixture.detectChanges(); + + expect(calendarInstance._currentView).toBe('year'); + + (calendarElement.querySelector('.mat-calendar-body-active') as HTMLElement).click(); + + const normalizedMonth: Date = fixture.componentInstance.selectedMonth; + expect(normalizedMonth.getMonth()).toEqual(0); + }); + + it('should emit the selected year on cell clicked in multiyear view', () => { + periodButton.click(); + fixture.detectChanges(); + + expect(calendarInstance._currentView).toBe('multi-year'); + expect(calendarInstance._activeDate).toEqual(new Date(2017, JAN, 31)); + + (calendarElement.querySelector('.mat-calendar-body-active') as HTMLElement).click(); + + fixture.detectChanges(); + + const normalizedYear: Date = fixture.componentInstance.selectedYear; + expect(normalizedYear.getFullYear()).toEqual(2017); + }); + it('should re-render when the i18n labels have changed', inject([MatDatepickerIntl], (intl: MatDatepickerIntl) => { const button = fixture.debugElement.nativeElement @@ -916,10 +950,18 @@ describe('MatCalendar', () => { @Component({ - template: `` + template: ` + + ` }) class StandardCalendar { selected: Date; + selectedYear: Date; + selectedMonth: Date; startDate = new Date(2017, JAN, 31); } diff --git a/src/lib/datepicker/calendar.ts b/src/lib/datepicker/calendar.ts index 2243ee53abad..1cbc49ebce93 100644 --- a/src/lib/datepicker/calendar.ts +++ b/src/lib/datepicker/calendar.ts @@ -107,6 +107,18 @@ export class MatCalendar implements AfterContentInit, OnDestroy, OnChanges { /** Emits when the currently selected date changes. */ @Output() readonly selectedChange: EventEmitter = new EventEmitter(); + /** + * Emits the year chosen in multiyear view. + * This doesn't imply a change on the selected date. + */ + @Output() readonly yearSelected: EventEmitter = new EventEmitter(); + + /** + * Emits the month chosen in year view. + * This doesn't imply a change on the selected date. + */ + @Output() readonly monthSelected: EventEmitter = new EventEmitter(); + /** Emits when any date is selected. */ @Output() readonly _userSelection: EventEmitter = new EventEmitter(); @@ -228,6 +240,16 @@ export class MatCalendar implements AfterContentInit, OnDestroy, OnChanges { } } + /** Handles year selection in the multiyear view. */ + _yearSelectedInMultiYearView(normalizedYear: D) { + this.yearSelected.emit(normalizedYear); + } + + /** Handles month selection in the year view. */ + _monthSelectedInYearView(normalizedMonth: D) { + this.monthSelected.emit(normalizedMonth); + } + _userSelected(): void { this._userSelection.emit(); } diff --git a/src/lib/datepicker/datepicker-content.html b/src/lib/datepicker/datepicker-content.html index 60c0cc747809..77269cecf75b 100644 --- a/src/lib/datepicker/datepicker-content.html +++ b/src/lib/datepicker/datepicker-content.html @@ -8,5 +8,7 @@ [dateFilter]="datepicker._dateFilter" [selected]="datepicker._selected" (selectedChange)="datepicker._select($event)" + (yearSelected)="datepicker._selectYear($event)" + (monthSelected)="datepicker._selectMonth($event)" (_userSelection)="datepicker.close()"> diff --git a/src/lib/datepicker/datepicker.md b/src/lib/datepicker/datepicker.md index e9cd81db7c3f..c2dcb2edb0cc 100644 --- a/src/lib/datepicker/datepicker.md +++ b/src/lib/datepicker/datepicker.md @@ -51,6 +51,31 @@ year containing the `startAt` date. +#### Watching the views for changes on selected years and months + +When a year or a month is selected in `multi-year` and `year` views respecively, the `yearSelected` +and `monthSelected` outputs emit a normalized date representing the chosen year or month. By +"normalized" we mean that the dates representing a year will have their month set to January and +their day set to the 1st. Dates representing months will have their day set to the 1st of the +month. For example, if `` is configured to work with javascript native Date +objects, the `yearSelected` will emit `new Date(2017, 0, 1)` if the user selects 2017 in +`multi-year` view. Similarly, `monthSelected` will emit `new Date(2017, 1, 0)` if the user +selects **February** in `year` view and the current date value of the connected `` was +something like `new Date(2017, MM, dd)` (the month and day are irrelevant in this case). + +Notice that the emitted value does not affect the current value in the connected ``, which +is only bound to the selection made in the `month` view. So if the end user closes the calendar +after choosing a year in `multi-view` mode (by pressing the `ESC` key, for example), the selected +year, emitted by `yearSelected` output, will not cause any change in the value of the date in the +associated ``. + +The following example uses `yearSelected` and `monthSelected` outputs to emulate a month and year +picker (if you're not familiar with the usage of `MomentDateAdapter` and `MAT_DATE_FORMATS` +you can [read more about them](#choosing-a-date-implementation-and-date-format-settings) below in +this document to fully understand the example). + + + ### Setting the selected date The type of values that the datepicker expects depends on the type of `DateAdapter` provided in your diff --git a/src/lib/datepicker/datepicker.spec.ts b/src/lib/datepicker/datepicker.spec.ts index 311f8897c75c..bb670a9751f5 100644 --- a/src/lib/datepicker/datepicker.spec.ts +++ b/src/lib/datepicker/datepicker.spec.ts @@ -433,12 +433,12 @@ describe('MatDatepicker', () => { }); }); - describe('datepicker with startView', () => { - let fixture: ComponentFixture; - let testComponent: DatepickerWithStartView; + describe('datepicker with startView set to year', () => { + let fixture: ComponentFixture; + let testComponent: DatepickerWithStartViewYear; beforeEach(fakeAsync(() => { - fixture = createComponent(DatepickerWithStartView, [MatNativeDateModule]); + fixture = createComponent(DatepickerWithStartViewYear, [MatNativeDateModule]); fixture.detectChanges(); testComponent = fixture.componentInstance; @@ -461,6 +461,73 @@ describe('MatDatepicker', () => { expect(firstCalendarCell.textContent) .toBe('JAN', 'Expected the calendar to be in year-view'); }); + + it('should fire yearSelected when user selects calendar year in year view', + fakeAsync(() => { + spyOn(testComponent, 'onYearSelection'); + expect(testComponent.onYearSelection).not.toHaveBeenCalled(); + + testComponent.datepicker.open(); + fixture.detectChanges(); + + const cells = document.querySelectorAll('.mat-calendar-body-cell'); + + dispatchMouseEvent(cells[0], 'click'); + fixture.detectChanges(); + flush(); + + expect(testComponent.onYearSelection).toHaveBeenCalled(); + }) + ); + }); + + describe('datepicker with startView set to multiyear', () => { + let fixture: ComponentFixture; + let testComponent: DatepickerWithStartViewMultiYear; + + beforeEach(fakeAsync(() => { + fixture = createComponent(DatepickerWithStartViewMultiYear, [MatNativeDateModule]); + fixture.detectChanges(); + + testComponent = fixture.componentInstance; + + spyOn(testComponent, 'onMultiYearSelection'); + })); + + afterEach(fakeAsync(() => { + testComponent.datepicker.close(); + fixture.detectChanges(); + flush(); + })); + + it('should start at the specified view', () => { + testComponent.datepicker.open(); + fixture.detectChanges(); + + const firstCalendarCell = document.querySelector('.mat-calendar-body-cell')!; + + // When the calendar is in year view, the first cell should be for a month rather than + // for a date. + expect(firstCalendarCell.textContent) + .toBe('2016', 'Expected the calendar to be in multi-year-view'); + }); + + it('should fire yearSelected when user selects calendar year in multiyear view', + fakeAsync(() => { + expect(testComponent.onMultiYearSelection).not.toHaveBeenCalled(); + + testComponent.datepicker.open(); + fixture.detectChanges(); + + const cells = document.querySelectorAll('.mat-calendar-body-cell'); + + dispatchMouseEvent(cells[0], 'click'); + fixture.detectChanges(); + flush(); + + expect(testComponent.onMultiYearSelection).toHaveBeenCalled(); + }) + ); }); describe('datepicker with ngModel', () => { @@ -1003,7 +1070,8 @@ describe('MatDatepicker', () => { expect(testComponent.onDateChange).toHaveBeenCalled(); expect(testComponent.onInput).not.toHaveBeenCalled(); expect(testComponent.onDateInput).toHaveBeenCalled(); - })); + }) + ); }); describe('with ISO 8601 strings as input', () => { @@ -1271,12 +1339,29 @@ class DatepickerWithStartAt { @Component({ template: ` - + `, }) -class DatepickerWithStartView { +class DatepickerWithStartViewYear { date = new Date(2020, JAN, 1); @ViewChild('d') datepicker: MatDatepicker; + + onYearSelection() {} +} + + +@Component({ + template: ` + + + `, +}) +class DatepickerWithStartViewMultiYear { + date = new Date(2020, JAN, 1); + @ViewChild('d') datepicker: MatDatepicker; + + onMultiYearSelection() {} } @@ -1321,6 +1406,7 @@ class DatepickerWithToggle { touchUI = true; } + @Component({ template: ` @@ -1332,6 +1418,7 @@ class DatepickerWithToggle { }) class DatepickerWithCustomIcon {} + @Component({ template: ` @@ -1394,6 +1481,7 @@ class DatepickerWithChangeAndInputEvents { onDateInput() {} } + @Component({ template: ` @@ -1406,6 +1494,7 @@ class DatepickerWithi18n { @ViewChild(MatDatepickerInput) datepickerInput: MatDatepickerInput; } + @Component({ template: ` @@ -1421,6 +1510,7 @@ class DatepickerWithISOStrings { @ViewChild(MatDatepickerInput) datepickerInput: MatDatepickerInput; } + @Component({ template: ` diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index 00fb9c046578..8dfc521deda1 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -164,6 +164,18 @@ export class MatDatepicker implements OnDestroy { */ @Output() readonly selectedChanged: EventEmitter = new EventEmitter(); + /** + * Emits selected year in multiyear view. + * This doesn't imply a change on the selected date. + */ + @Output() readonly yearSelected: EventEmitter = new EventEmitter(); + + /** + * Emits selected month in year view. + * This doesn't imply a change on the selected date. + */ + @Output() readonly monthSelected: EventEmitter = new EventEmitter(); + /** Classes to be passed to the date picker panel. Supports the same syntax as `ngClass`. */ @Input() panelClass: string | string[]; @@ -173,6 +185,7 @@ export class MatDatepicker implements OnDestroy { /** Emits when the datepicker has been closed. */ @Output('closed') closedStream: EventEmitter = new EventEmitter(); + /** Whether the calendar is open. */ @Input() get opened(): boolean { return this._opened; } @@ -253,6 +266,16 @@ export class MatDatepicker implements OnDestroy { } } + /** Emits the selected year in multiyear view */ + _selectYear(normalizedYear: D): void { + this.yearSelected.emit(normalizedYear); + } + + /** Emits selected month in year view */ + _selectMonth(normalizedMonth: D): void { + this.monthSelected.emit(normalizedMonth); + } + /** * Register an input with this datepicker. * @param input The datepicker input to register with this datepicker. diff --git a/src/lib/datepicker/multi-year-view.spec.ts b/src/lib/datepicker/multi-year-view.spec.ts index 1bca6d81042d..325b680bcf36 100644 --- a/src/lib/datepicker/multi-year-view.spec.ts +++ b/src/lib/datepicker/multi-year-view.spec.ts @@ -66,6 +66,16 @@ describe('MatMultiYearView', () => { expect(selectedEl.innerHTML.trim()).toBe('2039'); }); + it('should emit the selected year on cell clicked', () => { + let cellEls = multiYearViewNativeElement.querySelectorAll('.mat-calendar-body-cell'); + + (cellEls[1] as HTMLElement).click(); + fixture.detectChanges(); + + const normalizedYear: Date = fixture.componentInstance.selectedYear; + expect(normalizedYear.getFullYear()).toEqual(2017); + }); + it('should mark active date', () => { let cellEls = multiYearViewNativeElement.querySelectorAll('.mat-calendar-body-cell'); expect((cellEls[1] as HTMLElement).innerText.trim()).toBe('2017'); @@ -98,11 +108,13 @@ describe('MatMultiYearView', () => { @Component({ template: ` - `, + ` }) class StandardMultiYearView { date = new Date(2017, JAN, 1); selected = new Date(2020, JAN, 1); + selectedYear: Date; @ViewChild(MatYearView) yearView: MatYearView; } diff --git a/src/lib/datepicker/multi-year-view.ts b/src/lib/datepicker/multi-year-view.ts index 5c023839b894..65ebf88610b9 100644 --- a/src/lib/datepicker/multi-year-view.ts +++ b/src/lib/datepicker/multi-year-view.ts @@ -70,6 +70,9 @@ export class MatMultiYearView implements AfterContentInit { /** Emits when a new month is selected. */ @Output() readonly selectedChange: EventEmitter = new EventEmitter(); + /** Emits the selected year. This doesn't imply a change on the selected date */ + @Output() readonly yearSelected: EventEmitter = new EventEmitter(); + /** Grid of calendar cells representing the currently displayed years. */ _years: MatCalendarCell[][]; @@ -110,6 +113,7 @@ export class MatMultiYearView implements AfterContentInit { /** Handles when a new year is selected. */ _yearSelected(year: number) { + 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)); diff --git a/src/lib/datepicker/year-view.spec.ts b/src/lib/datepicker/year-view.spec.ts index 8937c7130323..b91914718ca4 100644 --- a/src/lib/datepicker/year-view.spec.ts +++ b/src/lib/datepicker/year-view.spec.ts @@ -71,6 +71,16 @@ describe('MatYearView', () => { expect(selectedEl.innerHTML.trim()).toBe('DEC'); }); + it('should emit the selected month on cell clicked', () => { + let cellEls = yearViewNativeElement.querySelectorAll('.mat-calendar-body-cell'); + + (cellEls[cellEls.length - 1] as HTMLElement).click(); + fixture.detectChanges(); + + const normalizedMonth: Date = fixture.componentInstance.selectedMonth; + expect(normalizedMonth.getMonth()).toEqual(11); + }); + it('should mark active date', () => { let cellEls = yearViewNativeElement.querySelectorAll('.mat-calendar-body-cell'); expect((cellEls[0] as HTMLElement).innerText.trim()).toBe('JAN'); @@ -113,11 +123,13 @@ describe('MatYearView', () => { @Component({ template: ` - `, + ` }) class StandardYearView { date = new Date(2017, JAN, 5); selected = new Date(2017, MAR, 10); + selectedMonth: Date; @ViewChild(MatYearView) yearView: MatYearView; } diff --git a/src/lib/datepicker/year-view.ts b/src/lib/datepicker/year-view.ts index f150ef153e1e..4b948f4ac789 100644 --- a/src/lib/datepicker/year-view.ts +++ b/src/lib/datepicker/year-view.ts @@ -65,6 +65,9 @@ export class MatYearView implements AfterContentInit { /** Emits when a new month is selected. */ @Output() readonly selectedChange: EventEmitter = new EventEmitter(); + /** Emits the selected month. This doesn't imply a change on the selected date */ + @Output() readonly monthSelected: EventEmitter = new EventEmitter(); + /** Grid of calendar cells representing the months of the year. */ _months: MatCalendarCell[][]; @@ -99,8 +102,13 @@ export class MatYearView implements AfterContentInit { /** Handles when a new month is selected. */ _monthSelected(month: number) { - let daysInMonth = this._dateAdapter.getNumDaysInMonth( - this._dateAdapter.createDate(this._dateAdapter.getYear(this.activeDate), month, 1)); + const normalizedDate = + this._dateAdapter.createDate(this._dateAdapter.getYear(this.activeDate), month, 1); + + this.monthSelected.emit(normalizedDate); + + const daysInMonth = this._dateAdapter.getNumDaysInMonth(normalizedDate); + this.selectedChange.emit(this._dateAdapter.createDate( this._dateAdapter.getYear(this.activeDate), month, Math.min(this._dateAdapter.getDate(this.activeDate), daysInMonth))); diff --git a/src/material-examples/datepicker-views-selection/datepicker-views-selection-example.css b/src/material-examples/datepicker-views-selection/datepicker-views-selection-example.css new file mode 100644 index 000000000000..7432308753e6 --- /dev/null +++ b/src/material-examples/datepicker-views-selection/datepicker-views-selection-example.css @@ -0,0 +1 @@ +/** No CSS for this example */ diff --git a/src/material-examples/datepicker-views-selection/datepicker-views-selection-example.html b/src/material-examples/datepicker-views-selection/datepicker-views-selection-example.html new file mode 100644 index 000000000000..148c5ce8a0b3 --- /dev/null +++ b/src/material-examples/datepicker-views-selection/datepicker-views-selection-example.html @@ -0,0 +1,6 @@ + + + + + diff --git a/src/material-examples/datepicker-views-selection/datepicker-views-selection-example.ts b/src/material-examples/datepicker-views-selection/datepicker-views-selection-example.ts new file mode 100644 index 000000000000..5a59b00d77ac --- /dev/null +++ b/src/material-examples/datepicker-views-selection/datepicker-views-selection-example.ts @@ -0,0 +1,58 @@ +import {Component} from '@angular/core'; +import {FormControl} from '@angular/forms'; +import {MatDatepicker} from '@angular/material/datepicker'; +import {MomentDateAdapter} from '@angular/material-moment-adapter'; +import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core'; + +// Depending on whether rollup is used, moment needs to be imported differently. +// Since Moment.js doesn't have a default export, we normally need to import using the `* as` +// syntax. However, rollup creates a synthetic default module and we thus need to import it using +// the `default as` syntax. +import * as _moment from 'moment'; +import {default as _rollupMoment, Moment} from 'moment'; +const moment = _rollupMoment || _moment; + +// See the Moment.js docs for the meaning of these formats: +// https://momentjs.com/docs/#/displaying/format/ +export const MY_FORMATS = { + parse: { + dateInput: 'MM/YYYY', + }, + display: { + dateInput: 'MM/YYYY', + monthYearLabel: 'MMM YYYY', + dateA11yLabel: 'LL', + monthYearA11yLabel: 'MMMM YYYY', + }, +}; + +/** @title Datepicker emulating a Year and month picker */ +@Component({ + selector: 'datepicker-views-selection-example', + templateUrl: 'datepicker-views-selection-example.html', + styleUrls: ['datepicker-views-selection-example.css'], + providers: [ + // `MomentDateAdapter` can be automatically provided by importing `MomentDateModule` in your + // application's root module. We provide it at the component level here, due to limitations of + // our example generation script. + {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]}, + + {provide: MAT_DATE_FORMATS, useValue: MY_FORMATS}, + ], +}) +export class DatepickerViewsSelectionExample { + date = new FormControl(moment()); + + chosenYearHandler(normalizedYear: Moment) { + const ctrlValue = this.date.value; + ctrlValue.year(normalizedYear.year()); + this.date.setValue(ctrlValue); + } + + chosenMonthHandler(normlizedMonth: Moment, datepicker: MatDatepicker) { + const ctrlValue = this.date.value; + ctrlValue.month(normlizedMonth.month()); + this.date.setValue(ctrlValue); + datepicker.close(); + } +} diff --git a/src/material-examples/material-module.ts b/src/material-examples/material-module.ts index a10465278135..abdd7c97891c 100644 --- a/src/material-examples/material-module.ts +++ b/src/material-examples/material-module.ts @@ -30,21 +30,21 @@ import { MatInputModule, MatListModule, MatMenuModule, + MatPaginatorModule, MatProgressBarModule, MatProgressSpinnerModule, MatRadioModule, MatSelectModule, + MatSidenavModule, MatSlideToggleModule, MatSliderModule, - MatSidenavModule, MatSnackBarModule, + MatSortModule, MatStepperModule, + MatTableModule, MatTabsModule, MatToolbarModule, MatTooltipModule, - MatPaginatorModule, - MatSortModule, - MatTableModule ] }) export class ExampleMaterialModule {}