From 9ba5d8434fda844ffc014d6304859fa89b0a091d Mon Sep 17 00:00:00 2001 From: Hubert Wesolowski Date: Tue, 15 Aug 2017 23:53:55 +0200 Subject: [PATCH] feat(datepicker): close calendar after choose the same date again (#6323) * feat: close calendar after choose the same date again * feat: close calendar by userSelection event * addressing pr comments * fix for tslint errors * addressing pr comments --- src/lib/datepicker/calendar.html | 3 +- src/lib/datepicker/calendar.ts | 7 +++++ src/lib/datepicker/datepicker-content.html | 3 +- src/lib/datepicker/datepicker.spec.ts | 32 +++++++++++++++++++--- src/lib/datepicker/datepicker.ts | 5 ++-- src/lib/datepicker/month-view.ts | 16 +++++++---- 6 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/lib/datepicker/calendar.html b/src/lib/datepicker/calendar.html index ab0532718bc1..5bed9b3e0cf0 100644 --- a/src/lib/datepicker/calendar.html +++ b/src/lib/datepicker/calendar.html @@ -48,7 +48,8 @@ [activeDate]="_activeDate" [selected]="selected" [dateFilter]="_dateFilterForViews" - (selectedChange)="_dateSelected($event)"> + (selectedChange)="_dateSelected($event)" + (userSelection)="_userSelected()"> implements AfterContentInit, OnDestroy { /** Emits when the currently selected date changes. */ @Output() selectedChange = new EventEmitter(); + /** Emits when any date is selected. */ + @Output() userSelection = new EventEmitter(); + /** Date filter for the month and year views. */ _dateFilterForViews = (date: D) => { return !!date && @@ -159,6 +162,10 @@ export class MdCalendar implements AfterContentInit, OnDestroy { } } + _userSelected(): void { + this.userSelection.emit(); + } + /** Handles month selection in the year view. */ _monthSelected(month: D): void { this._activeDate = month; diff --git a/src/lib/datepicker/datepicker-content.html b/src/lib/datepicker/datepicker-content.html index 0f3a70ec7dff..90fcc91b6097 100644 --- a/src/lib/datepicker/datepicker-content.html +++ b/src/lib/datepicker/datepicker-content.html @@ -6,5 +6,6 @@ [maxDate]="datepicker._maxDate" [dateFilter]="datepicker._dateFilter" [selected]="datepicker._selected" - (selectedChange)="datepicker._selectAndClose($event)"> + (selectedChange)="datepicker._select($event)" + (userSelection)="datepicker.close()"> diff --git a/src/lib/datepicker/datepicker.spec.ts b/src/lib/datepicker/datepicker.spec.ts index d1f14cde9551..9b608bd72e62 100644 --- a/src/lib/datepicker/datepicker.spec.ts +++ b/src/lib/datepicker/datepicker.spec.ts @@ -189,6 +189,30 @@ describe('MdDatepicker', () => { }); }); + it('clicking the currently selected date should close the calendar ' + + 'without firing selectedChanged', () => { + const selectedChangedSpy = + spyOn(testComponent.datepicker.selectedChanged, 'emit').and.callThrough(); + for (let changeCount = 1; changeCount < 3; changeCount++) { + const currentDay = changeCount; + testComponent.datepicker.open(); + fixture.detectChanges(); + + expect(document.querySelector('md-datepicker-content')).not.toBeNull(); + expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, currentDay)); + + let cells = document.querySelectorAll('.mat-calendar-body-cell'); + dispatchMouseEvent(cells[1], 'click'); + fixture.detectChanges(); + } + + fixture.whenStable().then(() => { + expect(selectedChangedSpy.calls.count()).toEqual(1); + expect(document.querySelector('md-dialog-container')).toBeNull(); + expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 2)); + }); + }); + it('startAt should fallback to input value', () => { expect(testComponent.datepicker.startAt).toEqual(new Date(2020, JAN, 1)); }); @@ -361,7 +385,7 @@ describe('MdDatepicker', () => { expect(testComponent.datepickerInput.value).toBeNull(); let selected = new Date(2017, JAN, 1); - testComponent.datepicker._selectAndClose(selected); + testComponent.datepicker._select(selected); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -388,7 +412,7 @@ describe('MdDatepicker', () => { expect(inputEl.classList).toContain('ng-pristine'); - testComponent.datepicker._selectAndClose(new Date(2017, JAN, 1)); + testComponent.datepicker._select(new Date(2017, JAN, 1)); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -434,7 +458,7 @@ describe('MdDatepicker', () => { expect(inputEl.classList).toContain('ng-untouched'); - testComponent.datepicker._selectAndClose(new Date(2017, JAN, 1)); + testComponent.datepicker._select(new Date(2017, JAN, 1)); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -478,7 +502,7 @@ describe('MdDatepicker', () => { expect(testComponent.datepickerInput.value).toBeNull(); let selected = new Date(2017, JAN, 1); - testComponent.datepicker._selectAndClose(selected); + testComponent.datepicker._select(selected); fixture.detectChanges(); expect(testComponent.formControl.value).toEqual(selected); diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index 854210cbf774..29ab0c40afa9 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -224,14 +224,13 @@ export class MdDatepicker implements OnDestroy { } } - /** Selects the given date and closes the currently open popup or dialog. */ - _selectAndClose(date: D): void { + /** Selects the given date */ + _select(date: D): void { let oldValue = this._selected; this._selected = date; if (!this._dateAdapter.sameDate(oldValue, this._selected)) { this.selectedChanged.emit(date); } - this.close(); } /** diff --git a/src/lib/datepicker/month-view.ts b/src/lib/datepicker/month-view.ts index 5d15ae7c4bcf..dcae6a54f400 100644 --- a/src/lib/datepicker/month-view.ts +++ b/src/lib/datepicker/month-view.ts @@ -67,6 +67,9 @@ export class MdMonthView implements AfterContentInit { /** Emits when a new date is selected. */ @Output() selectedChange = new EventEmitter(); + /** Emits when any date is selected. */ + @Output() userSelection = new EventEmitter(); + /** The label for this month (e.g. "January 2017"). */ _monthLabel: string; @@ -116,12 +119,15 @@ export class MdMonthView implements AfterContentInit { /** Handles when a new date is selected. */ _dateSelected(date: number) { - if (this._selectedDate == date) { - return; + if (this._selectedDate != date) { + const selectedYear = this._dateAdapter.getYear(this.activeDate); + const selectedMonth = this._dateAdapter.getMonth(this.activeDate); + const selectedDate = this._dateAdapter.createDate(selectedYear, selectedMonth, date); + + this.selectedChange.emit(selectedDate); } - this.selectedChange.emit(this._dateAdapter.createDate( - this._dateAdapter.getYear(this.activeDate), this._dateAdapter.getMonth(this.activeDate), - date)); + + this.userSelection.emit(); } /** Initializes this month view. */