@@ -16,9 +16,10 @@ import {
16
16
HostListener ,
17
17
NgModuleRef ,
18
18
OnInit ,
19
- AfterViewInit
19
+ AfterViewInit ,
20
+ Injector
20
21
} from '@angular/core' ;
21
- import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
22
+ import { ControlValueAccessor , NG_VALUE_ACCESSOR , NgControl , AbstractControl } from '@angular/forms' ;
22
23
import {
23
24
IgxCalendarComponent ,
24
25
IgxCalendarHeaderTemplateDirective ,
@@ -28,8 +29,8 @@ import {
28
29
isDateInRanges
29
30
} from '../calendar/index' ;
30
31
import { IgxIconModule } from '../icon/index' ;
31
- import { IgxInputGroupModule , IgxInputDirective , IgxInputGroupComponent } from '../input-group/index' ;
32
- import { Subject , fromEvent , animationFrameScheduler , interval } from 'rxjs' ;
32
+ import { IgxInputGroupModule , IgxInputDirective , IgxInputGroupComponent , IgxInputState } from '../input-group/index' ;
33
+ import { Subject , fromEvent , animationFrameScheduler , interval , Subscription } from 'rxjs' ;
33
34
import { filter , takeUntil , throttle } from 'rxjs/operators' ;
34
35
import { IgxOverlayOutletDirective } from '../directives/toggle/toggle.directive' ;
35
36
import { IgxTextSelectionModule } from '../directives/text-selection/text-selection.directive' ;
@@ -113,6 +114,8 @@ export enum PredefinedFormatOptions {
113
114
FullDate = 'fullDate'
114
115
}
115
116
117
+ const noop = ( ) => { } ;
118
+
116
119
/**
117
120
* **Ignite UI for Angular Date Picker** -
118
121
* [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/date_picker.html)
@@ -419,8 +422,12 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
419
422
this . _transformedDate = value ;
420
423
}
421
424
422
- constructor ( @Inject ( IgxOverlayService ) private _overlayService : IgxOverlayService , public element : ElementRef ,
423
- private _cdr : ChangeDetectorRef , private _moduleRef : NgModuleRef < any > ) { }
425
+ constructor ( @Inject (
426
+ IgxOverlayService ) private _overlayService : IgxOverlayService ,
427
+ public element : ElementRef ,
428
+ private _cdr : ChangeDetectorRef ,
429
+ private _moduleRef : NgModuleRef < any > ,
430
+ private _injector : Injector ) { }
424
431
425
432
/**
426
433
* Gets the input group template.
@@ -722,9 +729,15 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
722
729
@ViewChild ( 'readonlyInput' , { read : ElementRef } )
723
730
protected readonlyInput : ElementRef ;
724
731
725
- /*
726
- * @hidden
727
- */
732
+ /* @hidden */
733
+ @ViewChild ( 'editableInput' , { read : IgxInputDirective } )
734
+ protected editableInputDirective : IgxInputDirective ;
735
+
736
+ /* @hidden */
737
+ @ViewChild ( 'readonlyInput' , { read : IgxInputDirective } )
738
+ protected readonlyInputDirective : IgxInputDirective ;
739
+
740
+ /** @hidden @internal */
728
741
@ContentChild ( IgxInputDirective )
729
742
protected input : IgxInputDirective ;
730
743
@@ -778,6 +791,7 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
778
791
year : false
779
792
} ;
780
793
private _destroy$ = new Subject < boolean > ( ) ;
794
+ private _statusChanges$ : Subscription ;
781
795
private _componentID : string ;
782
796
private _format : string ;
783
797
private _value : Date ;
@@ -792,50 +806,43 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
792
806
private _transformedDate ;
793
807
private _onOpen = new EventEmitter < IgxDatePickerComponent > ( ) ;
794
808
private _onClose = new EventEmitter < IgxDatePickerComponent > ( ) ;
809
+ private _ngControl : NgControl = null ;
795
810
796
- /**
797
- * @hidden
798
- */
799
- @HostListener ( 'keydown.spacebar' , [ '$event' ] )
800
- @HostListener ( 'keydown.space' , [ '$event' ] )
801
- public onSpaceClick ( event : KeyboardEvent ) {
802
- this . openDialog ( this . getInputGroupElement ( ) ) ;
803
- event . preventDefault ( ) ;
804
- }
811
+ //#region ControlValueAccessor
805
812
806
- /**
807
- *Method that sets the selected date.
808
- *```typescript
809
- *public date = new Date();
810
- *@ViewChild ("MyDatePicker")
811
- *public datePicker: IgxDatePickerComponent;
812
- *ngAfterViewInit(){
813
- * this.datePicker.writeValue(this.date);
814
- *}
815
- *```
816
- *@param value The date you want to select.
817
- *@memberOf {@link IgxDatePickerComponent }
818
- */
813
+ private _onChangeCallback : ( _ : Date ) => void = noop ;
814
+
815
+ private _onTouchedCallback : ( ) => void = noop ;
816
+
817
+ /** @hidden @internal */
819
818
public writeValue ( value : Date ) {
820
- this . value = value ;
819
+ this . _value = value ;
820
+ // TODO: do we need next call
821
821
this . _cdr . markForCheck ( ) ;
822
822
}
823
823
824
- /**
825
- *@hidden
826
- */
824
+ /** @hidden @internal */
827
825
public registerOnChange ( fn : ( _ : Date ) => void ) { this . _onChangeCallback = fn ; }
828
826
829
- /**
830
- *@hidden
831
- */
827
+ /** @hidden @internal */
832
828
public registerOnTouched ( fn : ( ) => void ) { this . _onTouchedCallback = fn ; }
833
829
834
- /**
835
- *@hidden
836
- */
830
+ /** @hidden @internal */
837
831
public setDisabledState ( isDisabled : boolean ) : void { this . disabled = isDisabled ; }
838
832
833
+ //#endregion
834
+
835
+ /**
836
+ * @hidden
837
+ */
838
+ @HostListener ( 'keydown.spacebar' , [ '$event' ] )
839
+ @HostListener ( 'keydown.space' , [ '$event' ] )
840
+ public onSpaceClick ( event : KeyboardEvent ) {
841
+ this . openDialog ( this . getInputGroupElement ( ) ) ;
842
+ event . preventDefault ( ) ;
843
+ }
844
+
845
+
839
846
/** @hidden */
840
847
public getEditElement ( ) {
841
848
const inputElement = this . editableInput || this . readonlyInput || this . input ;
@@ -910,6 +917,8 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
910
917
}
911
918
this . inputMask = DatePickerUtil . getInputMask ( this . dateFormatParts ) ;
912
919
}
920
+
921
+ this . _ngControl = this . _injector . get < NgControl > ( NgControl , null ) ;
913
922
}
914
923
915
924
ngAfterViewInit ( ) {
@@ -919,6 +928,32 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
919
928
takeUntil ( this . _destroy$ )
920
929
) . subscribe ( ( res ) => this . onKeyDown ( res ) ) ;
921
930
}
931
+
932
+ if ( this . _ngControl ) {
933
+ this . _statusChanges$ = this . _ngControl . statusChanges . subscribe ( this . onStatusChanged . bind ( this ) ) ;
934
+ }
935
+ }
936
+
937
+ protected onStatusChanged ( ) {
938
+ if ( ( this . _ngControl . control . touched || this . _ngControl . control . dirty ) &&
939
+ ( this . _ngControl . control . validator || this . _ngControl . control . asyncValidator ) ) {
940
+ const input = this . readonlyInputDirective || this . editableInputDirective ;
941
+ if ( this . inputGroup . isFocused ) {
942
+ input . valid = this . _ngControl . valid ? IgxInputState . VALID : IgxInputState . INVALID ;
943
+ } else {
944
+ input . valid = this . _ngControl . valid ? IgxInputState . INITIAL : IgxInputState . INVALID ;
945
+ }
946
+ }
947
+ this . manageRequiredAsterisk ( ) ;
948
+ }
949
+
950
+ protected manageRequiredAsterisk ( ) : void {
951
+ if ( this . _ngControl && this . _ngControl . control . validator ) {
952
+ // Run the validation with empty object to check if required is enabled.
953
+ const error = this . _ngControl . control . validator ( { } as AbstractControl ) ;
954
+ this . inputGroup . isRequired = error && error . required ;
955
+ this . _cdr . markForCheck ( ) ;
956
+ }
922
957
}
923
958
924
959
/**
@@ -1031,6 +1066,14 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
1031
1066
}
1032
1067
}
1033
1068
1069
+ public mouseDown ( e ) {
1070
+ // if the click is not on the input but in input group
1071
+ // e.g. on prefix or sufix, prevent default and this way prevent blur
1072
+ if ( e . target !== this . getEditElement ( ) ) {
1073
+ e . preventDefault ( ) ;
1074
+ }
1075
+ }
1076
+
1034
1077
/**
1035
1078
* Close the calendar.
1036
1079
*
@@ -1086,7 +1129,20 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
1086
1129
*/
1087
1130
public onBlur ( event ) : void {
1088
1131
this . _isInEditMode = false ;
1089
- this . calculateDate ( event . target . value , event . type ) ;
1132
+ if ( this . mode === InteractionMode . DropDown ) {
1133
+ this . calculateDate ( event . target . value , event . type ) ;
1134
+ }
1135
+
1136
+ this . _onTouchedCallback ( ) ;
1137
+ if ( this . collapsed ) {
1138
+ const input = this . readonlyInputDirective || this . editableInputDirective || this . input ;
1139
+ if ( this . _ngControl && ! this . _ngControl . valid ) {
1140
+ console . log ( 'onBlur + collapsed + invalid' ) ;
1141
+ input . valid = IgxInputState . INVALID ;
1142
+ } else {
1143
+ input . valid = IgxInputState . INITIAL ;
1144
+ }
1145
+ }
1090
1146
}
1091
1147
1092
1148
/**
@@ -1373,9 +1429,6 @@ export class IgxDatePickerComponent implements IDatePicker, ControlValueAccessor
1373
1429
return DatePickerUtil . addPromptCharsEditMode ( this . dateFormatParts , this . value , changedValue ) ;
1374
1430
}
1375
1431
1376
- private _onTouchedCallback : ( ) => void = ( ) => { } ;
1377
-
1378
- private _onChangeCallback : ( _ : Date ) => void = ( ) => { } ;
1379
1432
}
1380
1433
1381
1434
/**
0 commit comments