import { Input , Output , OnInit , Injector , OnChanges , OnDestroy , Directive , forwardRef , EventEmitter , HostListener , ComponentRef , SimpleChanges , ComponentFactory , ViewContainerRef , ComponentFactoryResolver } from '@angular/core' ; import { DatePickerComponent } from './date-picker.component' ; import { DatePickerOptions } from './date-picker-options.provider' ; import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ; @ Directive ( { selector : '[DatePicker]' , providers : [ { provide : NG_VALUE_ACCESSOR , useExisting : forwardRef ( ( ) => DatePickerDirective ) , multi : true } ] } ) export class DatePickerDirective implements OnDestroy , OnChanges , OnInit , ControlValueAccessor { picker : ComponentRef < DatePickerComponent > ; appendToBodyElement : HTMLElement ; private _eventListeners : Array < ( ) => void > = [ ] ; private _ngModelOnChange : ( value : Date ) => { } ; private _ngModelOnTouched : ( ) => { } ; @ Input ( ) isOpen : boolean ; @ Input ( ) mode : string ; @ Input ( ) minDate : string ; @ Input ( ) maxDate : string ; @ Input ( ) use12Hours : boolean ; @ Input ( ) minuteStep : number = 1 ; @ Input ( ) value : Date = new Date ( ) ; @ Input ( ) mask : boolean ; @ Input ( ) title : string ; @ Input ( ) okText : string ; @ Input ( ) dismissText : string ; @ Input ( ) disabled : boolean ; @ Input ( ) locale : any ; @ Input ( ) appendToBody : boolean ; @ Input ( ) showErrorToast : boolean ; @ Input ( ) showErrorToastInterval : number ; @ Output ( ) onVisibleChange : EventEmitter < boolean > = new EventEmitter ( true ) ; @ Output ( ) onValueChange : EventEmitter < any > = new EventEmitter ( ) ; @ Output ( ) onOk : EventEmitter < any > = new EventEmitter ( ) ; @ Output ( ) onDismiss : EventEmitter < any > = new EventEmitter ( ) ; @ HostListener ( 'click' ) togglePicker ( ) { if ( ! this . picker ) { this . showPicker ( ) ; } else { this . hidePicker ( ) ; } } constructor ( private _viewContainerRef , private _defaultOptions , private _cfr ) { } showPicker ( ) { if ( ! this . picker && ! this . disabled ) { setTimeout ( ( ) => { this . _eventListeners = [ ] ; } ) ; const options = new DatePickerOptions ( ) ; Object . assign ( options , this . _defaultOptions , { hidePicker : ( event ) : void => { this . hidePicker ( ) ; } , updateNgModel : ( value ) : void => { if ( this . _ngModelOnChange ) { this . value = value ; this . _ngModelOnChange ( value ) ; } } } ) ; const optionalParams = [ 'mode' , 'minDate' , 'maxDate' , 'minuteStep' , 'value' , 'mask' , 'title' , 'okText' , 'dismissText' , 'disabled' , 'locale' , 'appendToBody' , 'showErrorToast' , 'showErrorToastInterval' , 'onOk' , 'onDismiss' , 'onValueChange' ] ; optionalParams . forEach ( param => { if ( typeof this [ param ] !== 'undefined' ) { ( options as any ) [ param ] = this [ param ] ; } } ) ; const componentFactory = this . _cfr . resolveComponentFactory ( DatePickerComponent ) ; const childInjector = Injector . create ( [ { provide : DatePickerOptions , useValue : options } ] ) ; this . picker = this . _viewContainerRef . createComponent ( componentFactory , this . _viewContainerRef . length , childInjector ) ; if ( options . appendToBody ) { this . appendToBodyElement = document . body . appendChild ( this . picker . location . nativeElement ) ; } this . onVisibleChange . emit ( true ) ; } } hidePicker ( ) { if ( this . appendToBodyElement ) { document . body . removeChild ( this . appendToBodyElement ) ; this . appendToBodyElement = null ; } if ( this . picker ) { this . picker . destroy ( ) ; delete this . picker ; this . onVisibleChange . emit ( false ) ; this . _eventListeners . forEach ( fn => fn ( ) ) ; this . _eventListeners = [ ] ; } } writeValue ( value ) { this . value = value ; } registerOnChange ( fn ) { this . _ngModelOnChange = fn ; } registerOnTouched ( fn ) { this . _ngModelOnTouched = fn ; } setDisabledState ( isDisabled ) { this . disabled = isDisabled ; } ngOnInit ( ) { this . onVisibleChange . emit ( false ) ; } ngOnChanges ( changes ) { if ( changes . isOpen ) { if ( changes . isOpen . currentValue === true ) { this . showPicker ( ) ; } else { this . hidePicker ( ) ; } } } ngOnDestroy ( ) { this . hidePicker ( ) ; } }