I have created a custom input formControl
, so I need to get/set its value via [(ngModel)]:
import { Component, Injector, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, FormGroup } from '@angular/forms';
@Component({
selector: 'time-picker',
template:
`<input type="text" class="clockpicker" [formControl]="selectedTime" />`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TimePickerComponent),
multi: true,
}]
})
export class TimePickerComponent implements OnInit, ControlValueAccessor {
selectedTime = new FormControl('');
constructor() { }
ngAfterViewInit() {
this.scriptLoader.load(
'assets/clockpicker/clockpicker.js'
);
}
writeValue(obj: any): void {
if (this.selectedTime) {
this.selectedTime.setValue(obj);
}
}
registerOnChange(fn: any): void {
this.selectedTime.valueChanges.subscribe(fn);
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
}
As you can see I have loaded a JavaScript third-party named clockpicker.js
. (It's just a simple clock picker), and here its code:
$(document).ready(function () {
$('.clockpicker').each(function (index, element) {
$(element).clockpicker({
afterDone: function () {
$(element).find('input[type="text"]').change();
}
});
});
});
Here is my problem:
When I directly type in this input so I can get the inserted value by [(ngModel)]
, but as you can see when the jQuery function fill the input value I can't get the filled value by [(ngModel)]
.
I know it's because it can't fire the registerOnChange
event in Angular life cycle even I use
$(element).find('input[type="text"]').change();
Nothing happen.
Angular can't know about changes that happen outside its zone. This means that you should tell to your Angular app that needs to run a change detection cycle to see if anything requires updating.
In your case, you should initialize the clock-picker
inside your component and detect changes with ChangeDetectorRef
. Please read more about NgZone
too that is useful to execute something that's outside you Angular zone.
Can be useful: