1
- import { Component , Input , ContentChild , ViewChild , AfterViewInit , AfterContentInit , OnDestroy } from '@angular/core' ;
1
+ import { Component , Input , ContentChild , ViewChild , AfterViewInit , AfterContentInit , OnDestroy , EventEmitter , Output } from '@angular/core' ;
2
2
import { InteractionMode } from '../core/enums' ;
3
3
import { IgxToggleDirective } from '../directives/toggle/toggle.directive' ;
4
4
import { IgxCalendarComponent , WEEKDAYS } from '../calendar/index' ;
@@ -38,6 +38,15 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
38
38
@Input ( )
39
39
public doneButtonText : string ;
40
40
41
+ @Output ( )
42
+ public rangeSelected : EventEmitter < IgxDateRangeComponent > ;
43
+
44
+ @Output ( )
45
+ public onOpened : EventEmitter < IgxDateRangeComponent > ;
46
+
47
+ @Output ( )
48
+ public onClosed : EventEmitter < IgxDateRangeComponent > ;
49
+
41
50
@ContentChild ( IgxDateRangeStartDirective , { read : IgxDateRangeStartDirective , static : false } )
42
51
public startInput : IgxDateRangeStartDirective ;
43
52
@@ -64,22 +73,29 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
64
73
private destroy : Subject < boolean > ;
65
74
66
75
constructor ( ) {
67
- this . mode = InteractionMode . Dialog ;
68
- this . monthsViewNumber = 1 ;
69
- this . weekStart = WEEKDAYS . SUNDAY ;
70
76
this . locale = 'en' ;
71
- this . todayButtonText = 'Today' ;
77
+ this . monthsViewNumber = 1 ;
72
78
this . doneButtonText = 'Done' ;
79
+ this . todayButtonText = 'Today' ;
80
+ this . weekStart = WEEKDAYS . SUNDAY ;
81
+ this . mode = InteractionMode . Dialog ;
73
82
this . destroy = new Subject < boolean > ( ) ;
83
+ this . onOpened = new EventEmitter < IgxDateRangeComponent > ( ) ;
84
+ this . onClosed = new EventEmitter < IgxDateRangeComponent > ( ) ;
85
+ this . rangeSelected = new EventEmitter < IgxDateRangeComponent > ( ) ;
74
86
}
75
87
76
88
public open ( ) {
77
89
this . showCalendar ( ) ;
78
90
}
79
91
92
+ public close ( ) {
93
+ this . hideCalendar ( ) ;
94
+ }
95
+
80
96
public showToday ( event : KeyboardEvent ) : void {
81
- const today = new Date ( ) ;
82
97
event . stopPropagation ( ) ;
98
+ const today = new Date ( ) ;
83
99
this . calendar . selectDate ( today ) ;
84
100
this . handleSelection ( this . calendar . selectedDates ) ;
85
101
}
@@ -107,8 +123,8 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
107
123
} )
108
124
} ;
109
125
this . dialogOverlaySettings = {
110
- closeOnOutsideClick : true ,
111
126
modal : true ,
127
+ closeOnOutsideClick : true ,
112
128
positionStrategy : new GlobalPositionStrategy ( )
113
129
} ;
114
130
}
@@ -117,29 +133,14 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
117
133
* @hidden
118
134
*/
119
135
public ngAfterViewInit ( ) : void {
120
- if ( this . mode === InteractionMode . DropDown ) {
121
- if ( this . singleInput ) {
122
- fromEvent ( this . singleInput . nativeElement , 'keydown' ) . pipe (
123
- takeUntil ( this . destroy )
124
- ) . subscribe ( ( evt : KeyboardEvent ) => this . onKeyDown ( evt ) ) ;
125
-
126
- this . toggle . onClosed . pipe (
127
- takeUntil ( this . destroy )
128
- ) . subscribe ( ( ) => this . singleInput . setFocus ( ) ) ;
129
- }
130
- if ( this . startInput && this . endInput ) {
131
- fromEvent ( this . startInput . nativeElement , 'keydown' ) . pipe (
132
- takeUntil ( this . destroy )
133
- ) . subscribe ( ( evt : KeyboardEvent ) => this . onKeyDown ( evt ) ) ;
134
-
135
- this . toggle . onClosed . pipe (
136
- takeUntil ( this . destroy )
137
- ) . subscribe ( ( ) => this . startInput . setFocus ( ) ) ;
138
-
139
- fromEvent ( this . endInput . nativeElement , 'keydown' ) . pipe (
140
- takeUntil ( this . destroy )
141
- ) . subscribe ( ( evt : KeyboardEvent ) => this . onKeyDown ( evt ) ) ;
142
- }
136
+ switch ( this . mode ) {
137
+ case InteractionMode . DropDown :
138
+ this . attachOnKeydown ( ) ;
139
+ this . applyFocusOnClose ( ) ;
140
+ break ;
141
+ case InteractionMode . Dialog :
142
+ this . applyFocusOnClose ( ) ;
143
+ break ;
143
144
}
144
145
}
145
146
@@ -159,18 +160,18 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
159
160
case KEYS . UP_ARROW :
160
161
case KEYS . UP_ARROW_IE :
161
162
if ( event . altKey ) {
162
- this . hideCalendar ( event ) ;
163
+ this . hideCalendar ( ) ;
163
164
}
164
165
break ;
165
166
case KEYS . DOWN_ARROW :
166
167
case KEYS . DOWN_ARROW_IE :
167
168
if ( event . altKey ) {
168
- this . showDropDown ( event ) ;
169
+ this . showDropDown ( ) ;
169
170
}
170
171
break ;
171
172
case KEYS . ESCAPE :
172
173
case KEYS . ESCAPE_IE :
173
- this . hideCalendar ( event ) ;
174
+ this . hideCalendar ( ) ;
174
175
break ;
175
176
}
176
177
}
@@ -184,8 +185,9 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
184
185
this . startInput || this . endInput ?
185
186
this . handleTwoInputSelection ( selectionData ) :
186
187
this . handleSingleInputSelection ( selectionData ) ;
188
+ this . rangeSelected . emit ( this ) ;
187
189
} else {
188
- // first selection in range
190
+ // first selection in the range
189
191
this . startInput || this . endInput ?
190
192
this . handleTwoInputSelection ( [ selectionData [ 0 ] , null ] ) :
191
193
this . handleSingleInputSelection ( [ selectionData [ 0 ] , null ] ) ;
@@ -195,7 +197,7 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
195
197
/**
196
198
* @hidden
197
199
*/
198
- public showCalendar ( event ?: MouseEvent ) : void {
200
+ public showCalendar ( event ?: MouseEvent | KeyboardEvent ) : void {
199
201
switch ( this . mode ) {
200
202
case InteractionMode . Dialog :
201
203
this . showDialog ( event ) ;
@@ -207,25 +209,25 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
207
209
// TODO: better error message
208
210
throw new Error ( 'Unknown mode.' ) ;
209
211
}
212
+ this . onOpened . emit ( this ) ;
210
213
}
211
214
212
215
/**
213
216
* @hidden
214
217
*/
215
- public hideCalendar ( event : MouseEvent | KeyboardEvent ) {
216
- event . stopPropagation ( ) ;
217
- event . preventDefault ( ) ;
218
+ public hideCalendar ( ) : void {
218
219
if ( ! this . toggle . collapsed ) {
219
- const element = event . target as HTMLElement ;
220
220
this . toggle . close ( ) ;
221
- element . focus ( ) ;
221
+ this . startInput ? this . startInput . nativeElement . focus ( ) :
222
+ this . singleInput . nativeElement . focus ( ) ;
222
223
}
224
+ this . onClosed . emit ( this ) ;
223
225
}
224
226
225
227
/**
226
228
* @hidden
227
229
*/
228
- public onOpened ( ) : void {
230
+ public onCalendarOpened ( ) : void {
229
231
requestAnimationFrame ( ( ) => {
230
232
this . calendar . daysView . focusActiveDate ( ) ;
231
233
} ) ;
@@ -253,13 +255,13 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
253
255
this . activateToggleOpen ( this . dropDownOverlaySettings ) ;
254
256
}
255
257
256
- private handleSingleInputSelection ( selectionData : Date [ ] ) {
258
+ private handleSingleInputSelection ( selectionData : Date [ ] ) : void {
257
259
if ( this . singleInput ) {
258
260
this . singleInput . value = this . extractRange ( selectionData ) ;
259
261
}
260
262
}
261
263
262
- private handleTwoInputSelection ( selectionData : Date [ ] ) {
264
+ private handleTwoInputSelection ( selectionData : Date [ ] ) : void {
263
265
const selectionRange = this . extractRange ( selectionData ) ;
264
266
if ( this . startInput ) {
265
267
this . startInput . value = selectionRange [ 0 ] ;
@@ -308,9 +310,39 @@ export class IgxDateRangeComponent implements AfterViewInit, AfterContentInit, O
308
310
}
309
311
310
312
private validateNgContent ( ) : void {
311
- if ( this . startInput && ! this . endInput || ! this . startInput && this . endInput ) {
313
+ if ( ! this . singleInput && ( ! this . startInput || ! this . endInput ) ) {
312
314
// TODO: better error message
313
315
throw new Error ( 'You must apply both igxDateRangeStart and igxDateRangeEnd if you are using two input elements.' ) ;
314
316
}
315
317
}
318
+
319
+ private attachOnKeydown ( ) : void {
320
+ if ( this . singleInput ) {
321
+ fromEvent ( this . singleInput . nativeElement , 'keydown' ) . pipe (
322
+ takeUntil ( this . destroy )
323
+ ) . subscribe ( ( evt : KeyboardEvent ) => this . onKeyDown ( evt ) ) ;
324
+ }
325
+ if ( this . startInput && this . endInput ) {
326
+ fromEvent ( this . startInput . nativeElement , 'keydown' ) . pipe (
327
+ takeUntil ( this . destroy )
328
+ ) . subscribe ( ( evt : KeyboardEvent ) => this . onKeyDown ( evt ) ) ;
329
+
330
+ fromEvent ( this . endInput . nativeElement , 'keydown' ) . pipe (
331
+ takeUntil ( this . destroy )
332
+ ) . subscribe ( ( evt : KeyboardEvent ) => this . onKeyDown ( evt ) ) ;
333
+ }
334
+ }
335
+
336
+ private applyFocusOnClose ( ) {
337
+ if ( this . singleInput ) {
338
+ this . toggle . onClosed . pipe (
339
+ takeUntil ( this . destroy )
340
+ ) . subscribe ( ( ) => this . singleInput . setFocus ( ) ) ;
341
+ }
342
+ if ( this . startInput ) {
343
+ this . toggle . onClosed . pipe (
344
+ takeUntil ( this . destroy )
345
+ ) . subscribe ( ( ) => this . startInput . setFocus ( ) ) ;
346
+ }
347
+ }
316
348
}
0 commit comments