From 0d080f428509b6cf594831d61d245850c247617a Mon Sep 17 00:00:00 2001 From: SAndreeva Date: Tue, 12 Feb 2019 16:11:05 +0200 Subject: [PATCH] feat(month picker): various bug fixes and enhancements #3126 --- .../src/lib/calendar/calendar.component.html | 15 +-- .../lib/calendar/calendar.component.spec.ts | 6 +- .../src/lib/calendar/calendar.component.ts | 100 +++++++++++++----- .../calendar/days-view/days-view.component.ts | 66 ++++++++---- .../months-view/months-view.component.ts | 6 +- .../years-view/years-view.component.ts | 6 +- .../month-picker/month-picker.component.html | 4 +- .../month-picker/month-picker.component.ts | 53 ++++++++-- .../calendar-views/calendar-views.sample.html | 33 ++++-- .../calendar-views/calendar-views.sample.ts | 35 +++++- 10 files changed, 238 insertions(+), 86 deletions(-) diff --git a/projects/igniteui-angular/src/lib/calendar/calendar.component.html b/projects/igniteui-angular/src/lib/calendar/calendar.component.html index 858d4715bc4..e8648ecdea3 100644 --- a/projects/igniteui-angular/src/lib/calendar/calendar.component.html +++ b/projects/igniteui-angular/src/lib/calendar/calendar.component.html @@ -4,10 +4,10 @@ - + {{ formattedMonth(viewDate) }} - + {{ formattedYear(viewDate) }} @@ -22,14 +22,14 @@

-
+
keyboard_arrow_left
-
+
keyboard_arrow_right
@@ -39,11 +39,12 @@

[locale]="locale" [value]="value" [weekStart]="weekStart" + [formatOptions]="formatOptions" [viewDate]="viewDate" [selection]="selection" [disabledDates]="disabledDates" [specialDates]="specialDates" - (onViewChnaged)="viewChanged($event)" + (onViewChanged)="viewChanged($event)" (onDateSelection)="childClicked($event)">

@@ -52,12 +53,12 @@

[date]="viewDate" [locale]="locale" [monthFormat]="_formatOptions.month" - (onMonthSelection)="changeMonth($event)" > + (onSelection)="changeMonth($event)" > + (onSelection)="changeYear($event)"> diff --git a/projects/igniteui-angular/src/lib/calendar/calendar.component.spec.ts b/projects/igniteui-angular/src/lib/calendar/calendar.component.spec.ts index 1d6828dea6b..ffcdbb4c4f3 100644 --- a/projects/igniteui-angular/src/lib/calendar/calendar.component.spec.ts +++ b/projects/igniteui-angular/src/lib/calendar/calendar.component.spec.ts @@ -1630,7 +1630,7 @@ describe('IgxCalendar', () => { expect(prev.nativeElement).toBe(document.activeElement); - UIInteractions.simulateKeyDownEvent(prev.nativeElement, 'Space'); + UIInteractions.simulateKeyDownEvent(prev.nativeElement, 'Enter'); fixture.detectChanges(); expect(calendar.viewDate.getMonth()).toEqual(4); @@ -1640,8 +1640,8 @@ describe('IgxCalendar', () => { expect(next.nativeElement).toBe(document.activeElement); - UIInteractions.simulateKeyDownEvent(next.nativeElement, 'Space'); - UIInteractions.simulateKeyDownEvent(next.nativeElement, 'Space'); + UIInteractions.simulateKeyDownEvent(next.nativeElement, 'Enter'); + UIInteractions.simulateKeyDownEvent(next.nativeElement, 'Enter'); fixture.detectChanges(); expect(calendar.viewDate.getMonth()).toEqual(6); diff --git a/projects/igniteui-angular/src/lib/calendar/calendar.component.ts b/projects/igniteui-angular/src/lib/calendar/calendar.component.ts index 7b612a896c4..d53c6e6e9fb 100644 --- a/projects/igniteui-angular/src/lib/calendar/calendar.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/calendar.component.ts @@ -2,12 +2,10 @@ import { transition, trigger, useAnimation } from '@angular/animations'; import { Component, ContentChild, - EventEmitter, forwardRef, HostBinding, HostListener, Input, - Output, ViewChild, ElementRef } from '@angular/core'; @@ -111,17 +109,6 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { @Input() public vertical = false; - /** - * Emits an event when a selection is made in the calendar. - * Provides reference the `selectedDates` property in the `IgxCalendarComponent`. - * ```html - * - * ``` - * @memberof IgxCalendarComponent - */ - @Output() - public onSelection = new EventEmitter(); - /** * The default `tabindex` attribute for the component. * @@ -174,6 +161,18 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { @ViewChild('days', {read: IgxDaysViewComponent}) public daysView: IgxDaysViewComponent; + /** + * @hidden + */ + @ViewChild('monthsBtn') + public monthsBtn: ElementRef; + + /** + * @hidden + */ + @ViewChild('yearsBtn') + public yearsBtn: ElementRef; + /** * @hidden */ @@ -372,17 +371,24 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { this.viewDate = this.calendarModel.timedelta(this.viewDate, 'month', -1); this._monthAction = 'prev'; - this.daysView.isKeydownTrigger = false; + if (this.daysView) { + this.daysView.isKeydownTrigger = false; + } } /** * @hidden */ public previousMonthKB(event) { - event.preventDefault(); + if (event.key === KEYS.SPACE || event.key === KEYS.SPACE_IE || event.key === KEYS.ENTER) { + event.preventDefault(); + event.stopPropagation(); - this.previousMonth(); - this.daysView.isKeydownTrigger = true; + this.previousMonth(); + if (this.daysView) { + this.daysView.isKeydownTrigger = true; + } + } } /** @@ -392,17 +398,24 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { this.viewDate = this.calendarModel.timedelta(this.viewDate, 'month', 1); this._monthAction = 'next'; - this.daysView.isKeydownTrigger = false; + if (this.daysView) { + this.daysView.isKeydownTrigger = false; + } } /** * @hidden */ public nextMonthKB(event) { - event.preventDefault(); + if (event.key === KEYS.SPACE || event.key === KEYS.SPACE_IE || event.key === KEYS.ENTER) { + event.preventDefault(); + event.stopPropagation(); - this.nextMonth(); - this.daysView.isKeydownTrigger = true; + this.nextMonth(); + if (this.daysView) { + this.daysView.isKeydownTrigger = true; + } + } } /** @@ -462,7 +475,9 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { this.viewDate = new Date(event.getFullYear(), this.viewDate.getMonth()); this._activeView = CalendarView.DEFAULT; - this.elementRef.nativeElement.focus(); + requestAnimationFrame(() => { + this.yearsBtn.nativeElement.focus(); + }); } /** @@ -472,7 +487,9 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { this.viewDate = new Date(this.viewDate.getFullYear(), event.getMonth()); this._activeView = CalendarView.DEFAULT; - this.elementRef.nativeElement.focus(); + requestAnimationFrame(() => { + this.monthsBtn.nativeElement.focus(); + }); } /** @@ -515,6 +532,19 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { } } + /** + * Deselects date(s) (based on the selection type). + *```typescript + * this.calendar.deselectDate(new Date(`2018-06-12`)); + *```` + */ + public deselectDate(value?: Date | Date[]) { + super.deselectDate(value); + + this.daysView.selectedDates = this.selectedDates; + this._onChangeCallback(this.selectedDates); + } + /** * @hidden */ @@ -523,7 +553,9 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { event.preventDefault(); this.previousMonth(); - this.daysView.isKeydownTrigger = true; + if (this.daysView) { + this.daysView.isKeydownTrigger = true; + } } /** @@ -534,7 +566,9 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { event.preventDefault(); this.nextMonth(); - this.daysView.isKeydownTrigger = true; + if (this.daysView) { + this.daysView.isKeydownTrigger = true; + } } /** @@ -545,7 +579,9 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { event.preventDefault(); this.previousYear(); - this.daysView.isKeydownTrigger = true; + if (this.daysView) { + this.daysView.isKeydownTrigger = true; + } } /** @@ -556,7 +592,9 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { event.preventDefault(); this.nextYear(); - this.daysView.isKeydownTrigger = true; + if (this.daysView) { + this.daysView.isKeydownTrigger = true; + } } /** @@ -564,7 +602,9 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { */ @HostListener('keydown.home', ['$event']) public onKeydownHome(event: KeyboardEvent) { - this.daysView.onKeydownHome(event); + if (this.daysView) { + this.daysView.onKeydownHome(event); + } } /** @@ -572,7 +612,9 @@ export class IgxCalendarComponent extends IgxDaysViewComponent { */ @HostListener('keydown.end', ['$event']) public onKeydownEnd(event: KeyboardEvent) { - this.daysView.onKeydownEnd(event); + if (this.daysView) { + this.daysView.onKeydownEnd(event); + } } /** diff --git a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts index d8e2f0c6c91..274e777e302 100644 --- a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts @@ -301,12 +301,18 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { public changeDaysView = false; /** - * Emits an event when a selection is made in the days view. - * Provides reference the `date` property in the `IgxDaysViewComponent`. + * Emits an event when a date is selected. + * Provides reference the `selectedDates` property. * ```html - * + * * ``` - * @memberof IgxDaysViewComponent + * @memberof IgxCalendarComponent + */ + @Output() + public onSelection = new EventEmitter(); + + /** + * @hidden */ @Output() public onDateSelection = new EventEmitter(); @@ -315,7 +321,7 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { * @hidden */ @Output() - public onViewChnaged = new EventEmitter(); + public onViewChanged = new EventEmitter(); /** * @hidden @@ -373,10 +379,6 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { *@hidden */ protected formatterYear; - /** - *@hidden - */ - protected selectedDates; /** *@hidden */ @@ -403,6 +405,10 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { * @hidden */ public outOfRangeDates: DateRangeDescriptor[]; + /** + *@hidden + */ + public selectedDates; /** * The default css class applied to the component. @@ -412,6 +418,14 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { @HostBinding('class.igx-calendar') public styleClass = true; + /** + * The default `tabindex` attribute for the component. + * + * @hidden + */ + @HostBinding('attr.tabindex') + public tabindex = 0; + /** * @hidden */ @@ -653,11 +667,13 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { this.animationAction = 'prev'; this.callback = (items?, next?) => { - const day = items.find((item) => item.date.date.getTime() === next.getTime()).nativeElement; - this.focusPreviousUpDate(day, true); + const day = items.find((item) => item.date.date.getTime() === next.getTime()); + if (day) { + this.focusPreviousUpDate(day.nativeElement, true); + } }; - this.onViewChnaged.emit(this._nextDate); + this.onViewChanged.emit(this._nextDate); } } @@ -689,11 +705,13 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { this.animationAction = 'next'; this.callback = (items?, next?) => { - const day = items.find((item) => item.date.date.getTime() === next.getTime()).nativeElement; - this.focusNextDownDate(day, true); + const day = items.find((item) => item.date.date.getTime() === next.getTime()); + if (day) { + this.focusNextDownDate(day.nativeElement, true); + } }; - this.onViewChnaged.emit(this._nextDate); + this.onViewChanged.emit(this._nextDate); } } @@ -723,11 +741,13 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { this.animationAction = 'prev'; this.callback = (items?, next?) => { - const day = items.find((item) => item.date.date.getTime() === next.getTime()).nativeElement; - this.focusPreviousDate(day); + const day = items.find((item) => item.date.date.getTime() === next.getTime()); + if (day) { + this.focusPreviousDate(day.nativeElement); + } }; - this.onViewChnaged.emit(this._nextDate); + this.onViewChanged.emit(this._nextDate); } } @@ -758,11 +778,13 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { this.animationAction = 'next'; this.callback = (items?, next?) => { - const day = items.find((item) => item.date.date.getTime() === next.getTime()).nativeElement; - this.focusNextDate(day); + const day = items.find((item) => item.date.date.getTime() === next.getTime()); + if (day) { + this.focusNextDate(day.nativeElement); + } }; - this.onViewChnaged.emit(this._nextDate); + this.onViewChanged.emit(this._nextDate); } } @@ -964,6 +986,8 @@ export class IgxDaysViewComponent implements ControlValueAccessor, DoCheck { public selectDay(event) { this.selectDateFromClient(event.date); this.onDateSelection.emit(event); + + this.onSelection.emit(this.selectedDates); } /** diff --git a/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.ts b/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.ts index 2bc3a67f5d2..eef7b559751 100644 --- a/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.ts @@ -110,7 +110,7 @@ export class IgxMonthsViewComponent implements ControlValueAccessor { * @memberof IgxMonthsViewComponent */ @Output() - public onMonthSelection = new EventEmitter(); + public onSelection = new EventEmitter(); /** * The default css class applied to the component. @@ -199,7 +199,7 @@ export class IgxMonthsViewComponent implements ControlValueAccessor { *@hidden */ public selectMonth(event) { - this.onMonthSelection.emit(event); + this.onSelection.emit(event); this.date = event; this._onChangeCallback(this.date); @@ -366,7 +366,7 @@ export class IgxMonthsViewComponent implements ControlValueAccessor { */ @HostListener('keydown.enter') public onKeydownEnter() { - this.onMonthSelection.emit(this.date); + this.onSelection.emit(this.date); this._onChangeCallback(this.date); } } diff --git a/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.ts b/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.ts index f1436fd2c5b..c488bf1705a 100644 --- a/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.ts @@ -117,7 +117,7 @@ export class IgxYearsViewComponent implements ControlValueAccessor { * @memberof IgxYearsViewComponent */ @Output() - public onYearSelection = new EventEmitter(); + public onSelection = new EventEmitter(); /** * The default css class applied to the component. @@ -199,7 +199,7 @@ export class IgxYearsViewComponent implements ControlValueAccessor { *@hidden */ public selectYear(event) { - this.onYearSelection.emit(event); + this.onSelection.emit(event); this.date = event; this._onChangeCallback(this.date); @@ -274,7 +274,7 @@ export class IgxYearsViewComponent implements ControlValueAccessor { */ @HostListener('keydown.enter') public onKeydownEnter() { - this.onYearSelection.emit(this.date); + this.onSelection.emit(this.date); this._onChangeCallback(this.date); } diff --git a/projects/igniteui-angular/src/lib/month-picker/month-picker.component.html b/projects/igniteui-angular/src/lib/month-picker/month-picker.component.html index 8349623f74d..3713d4e58f6 100644 --- a/projects/igniteui-angular/src/lib/month-picker/month-picker.component.html +++ b/projects/igniteui-angular/src/lib/month-picker/month-picker.component.html @@ -18,12 +18,12 @@ [date]="viewDate" [locale]="locale" [monthFormat]="_formatOptions.month" - (onMonthSelection)="selectMonth($event)"> + (onSelection)="selectMonth($event)">

+ (onSelection)="selectYear($event)"> diff --git a/projects/igniteui-angular/src/lib/month-picker/month-picker.component.ts b/projects/igniteui-angular/src/lib/month-picker/month-picker.component.ts index a37d0832051..d5c1ef8a8fb 100644 --- a/projects/igniteui-angular/src/lib/month-picker/month-picker.component.ts +++ b/projects/igniteui-angular/src/lib/month-picker/month-picker.component.ts @@ -1,10 +1,11 @@ import { Component, - NgModule + NgModule, + HostListener } from '@angular/core'; import { IgxCalendarModule, CalendarView, IgxCalendarComponent } from '../calendar/index'; import { IgxIconModule } from '../icon/index'; -import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; +import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { trigger, transition, useAnimation } from '@angular/animations'; import { fadeIn, scaleInCenter, slideInLeft, slideInRight } from '../animations/main'; @@ -45,35 +46,75 @@ import { fadeIn, scaleInCenter, slideInLeft, slideInRight } from '../animations/ }) export class IgxMonthPickerComponent extends IgxCalendarComponent { + /** + * @hidden + */ public yearAction = ''; + /** + * @hidden + */ public animationDone() { this.yearAction = ''; - this.monthsView.el.nativeElement.focus(); } + /** + * @hidden + */ public nextYear() { this.yearAction = 'next'; super.nextYear(); } + /** + * @hidden + */ public previousYear() { this.yearAction = 'prev'; super.previousYear(); } + /** + * @hidden + */ public selectMonth(event: Date) { this.viewDate = new Date(event.getFullYear(), event.getMonth(), event.getDate()); this._onChangeCallback(this.viewDate); + + this.onSelection.emit(this.viewDate); } + /** + * @hidden + */ public selectYear(event: Date) { this.viewDate = new Date(event.getFullYear(), event.getMonth(), event.getDate()); this.activeView = CalendarView.DEFAULT; + } + + /** + * @hidden + */ + @HostListener('keydown.pageup', ['$event']) + public onKeydownPageUp(event: KeyboardEvent) { + super.onKeydownShiftPageUp(event); + } + + /** + * @hidden + */ + @HostListener('keydown.pagedown', ['$event']) + public onKeydownPageDown(event: KeyboardEvent) { + super.onKeydownShiftPageDown(event); + } - requestAnimationFrame(() => { - this.monthsView.el.nativeElement.focus(); - }); + /** + * @hidden + */ + @HostListener('keydown.shift.pageup', ['$event']) + @HostListener('keydown.shift.pagedown', ['$event']) + public onKeydownShiftPageDownUp(event: KeyboardEvent) { + event.stopPropagation(); } } diff --git a/src/app/calendar-views/calendar-views.sample.html b/src/app/calendar-views/calendar-views.sample.html index 0eba5dda6ac..cb18bb19cfd 100644 --- a/src/app/calendar-views/calendar-views.sample.html +++ b/src/app/calendar-views/calendar-views.sample.html @@ -2,16 +2,21 @@ Calendar Views
-
+

Default Calendar

+
+ + +
+ [disabledDates]="disabledDates" + [selection]="'multi'" + (onSelection)="onSelection($event)">
@@ -24,7 +29,8 @@

Month Picker

+ [locale]="localeDe" + (onSelection)="onSelection($event)">
@@ -36,24 +42,35 @@

Month Picker

- + +
- + +
+
+ + +
+ [selection]="'single'" + (onSelection)="onSelection($event)">
diff --git a/src/app/calendar-views/calendar-views.sample.ts b/src/app/calendar-views/calendar-views.sample.ts index 612d6abefe1..00b68b09cce 100644 --- a/src/app/calendar-views/calendar-views.sample.ts +++ b/src/app/calendar-views/calendar-views.sample.ts @@ -11,14 +11,12 @@ export class CalendarViewsSampleComponent implements OnInit { @ViewChild('calendar') calendar: IgxCalendarComponent; @ViewChild('daysView') daysView: IgxDaysViewComponent; + dates: Date | Date[]; date = new Date(2018, 8, 5); date1 = new Date(2019, 1, 7); - dates = [ - new Date(2019, 1, 7), - new Date(2019, 1, 8) - ]; viewDate = new Date(2019, 1, 7); + selection = new Date(2018, 1, 13); locale = 'en'; localeFr = 'fr'; @@ -48,6 +46,11 @@ export class CalendarViewsSampleComponent implements OnInit { }]; ngOnInit() { + this.dates = [ + new Date(2019, 1, 7), + new Date(2019, 1, 8) + ]; + this.daysView.disabledDates = [{ type: DateRangeType.Between, dateRange: [ new Date(2019, 1, 22), @@ -61,4 +64,28 @@ export class CalendarViewsSampleComponent implements OnInit { ] }]; } + + onSelection(event) { + console.log(event); + } + + select() { + // this.calendar.selectDate(new Date(2019, 1, 13)); + this.calendar.selectDate([new Date(2019, 1, 13), new Date(2019, 1, 14)]); + } + + deselect() { + // this.calendar.deselectDate(new Date(2019, 1, 13)); + this.calendar.deselectDate([new Date(2019, 1, 7), new Date(2019, 1, 8), new Date(2019, 1, 13), new Date(2019, 1, 14)]); + } + + selectDV() { + this.daysView.selectDate(new Date(2019, 1, 13)); + // this.daysView.selectDate([new Date(2019, 1, 13), new Date(2019, 1, 14)]); + } + + deselectDV() { + this.daysView.deselectDate(new Date(2019, 1, 13)); + // this.daysView.deselectDate([new Date(2019, 1, 13), new Date(2019, 1, 14)]); + } }