|
import { |
|
ChangeDetectorRef, |
|
Directive, |
|
DoCheck, |
|
ElementRef, |
|
EventEmitter, |
|
forwardRef, |
|
HostListener, |
|
Input, |
|
KeyValueDiffer, |
|
KeyValueDiffers, |
|
OnDestroy, |
|
OnInit, |
|
Output, |
|
} from '@angular/core'; |
|
import { NG_VALUE_ACCESSOR } from '@angular/forms'; |
|
import { |
|
Options, |
|
DateTime, |
|
TempusDominus, |
|
Namespace, |
|
} from '@eonasdan/tempus-dominus'; |
|
|
|
@Directive({ |
|
selector: '[NgTempusDominusInput]', |
|
exportAs: 'NgTempusDominusBootstrapInput', |
|
providers: [ |
|
{ |
|
provide: NG_VALUE_ACCESSOR, |
|
useExisting: forwardRef(() => NgTempusDominusInputDirective), |
|
multi: true, |
|
}, |
|
], |
|
}) |
|
export class NgTempusDominusInputDirective |
|
implements OnInit, OnDestroy, DoCheck |
|
{ |
|
_value: DateTime; |
|
private _options: Options = {} as Options; |
|
private tdSubscription: { unsubscribe: () => void }; |
|
@Input() set options(value: Options) { |
|
if (value !== null) { |
|
this._options = value; |
|
} |
|
} |
|
|
|
get options(): any { |
|
return this._options; |
|
} |
|
|
|
@Output() click: EventEmitter<any> = new EventEmitter<any>(); |
|
private dpInitialized: boolean; |
|
private inputOnly: boolean; |
|
|
|
datepicker: TempusDominus; |
|
private optionsDiffer: KeyValueDiffer<string, any>; |
|
private _onTouched: any = () => {}; |
|
private _onChange: any = () => {}; |
|
|
|
constructor( |
|
private changeDetector: ChangeDetectorRef, |
|
protected el: ElementRef, |
|
private differs: KeyValueDiffers |
|
) { |
|
this.dpInitialized = false; |
|
} |
|
|
|
ngOnInit(): void { |
|
const parent = this.el.nativeElement.parentNode; |
|
this.inputOnly = !parent.classList.contains('input-group'); |
|
this.datepicker = new TempusDominus( |
|
!this.inputOnly ? parent : this.el.nativeElement, |
|
this.options |
|
); |
|
this.tdSubscription = this.datepicker.subscribe( |
|
Namespace.events.change, |
|
(e) => { |
|
if (e.date && e.date !== this.value) { |
|
this.value = e.date || null; |
|
} /* else { |
|
const date = moment(e.target.value, this.options.format); |
|
if (date.isValid()) { |
|
this.value = date; |
|
} |
|
}*/ |
|
} |
|
) as any; |
|
this.optionsDiffer = this.differs.find(this.options).create(); |
|
this.dpInitialized = true; |
|
} |
|
|
|
@HostListener('blur') onBlur() { |
|
this._onTouched(); |
|
} |
|
|
|
@HostListener('focus') onFocus() { |
|
if (this.inputOnly) { |
|
this.datepicker.show(); |
|
} |
|
} |
|
|
|
/** |
|
* For click outside of input, for input only |
|
* @param event event object |
|
*/ |
|
@HostListener('document:click', ['$event']) |
|
outsideClick(event): void { |
|
let targetElement: HTMLElement = event?.target; |
|
if (!targetElement || !this.inputOnly || this.options.inline) { |
|
return; |
|
} |
|
const clickedInside = this.el.nativeElement.contains(targetElement); |
|
if (!clickedInside) { |
|
this.datepicker.hide(); |
|
} |
|
} |
|
|
|
get value() { |
|
return this._value || null; |
|
} |
|
|
|
set value(val) { |
|
this._value = val; |
|
this._onChange(val); |
|
if (val) { |
|
this._onTouched(); |
|
} |
|
this.changeDetector.markForCheck(); |
|
} |
|
|
|
writeValue(value) { |
|
// if we have a previous value and current value is falsy |
|
// clear the picker |
|
if (this._value && !value) { |
|
this.value = null; |
|
this.datepicker.clear(); |
|
} |
|
this.value = value; |
|
this.setDpValue(value); |
|
} |
|
|
|
registerOnChange(fn) { |
|
this._onChange = fn; |
|
} |
|
|
|
registerOnTouched(fn: () => any): void { |
|
this._onTouched = fn; |
|
} |
|
|
|
private setDpValue(val) { |
|
if (!this.dpInitialized) { |
|
return; |
|
} |
|
if (val) { |
|
this.datepicker.dates.setValue(this.value, 0); |
|
} |
|
} |
|
|
|
setDisabledState(isDisabled: boolean): void { |
|
if (isDisabled) { |
|
this.datepicker.disable(); |
|
return; |
|
} |
|
this.datepicker.enable(); |
|
} |
|
|
|
ngDoCheck() { |
|
if (this.dpInitialized) { |
|
const changes = this.optionsDiffer.diff(this.options); |
|
if (changes) { |
|
this.datepicker.updateOptions(this.options); |
|
} |
|
} |
|
} |
|
|
|
ngOnDestroy(): void { |
|
this.tdSubscription.unsubscribe(); |
|
this.datepicker?.dispose(); |
|
} |
|
|
|
toggle(): void { |
|
this.datepicker.toggle(); |
|
} |
|
} |
It would be good to know what happens in
BaseWrapperComponent
andapp-field-wrapper
.