I am using Angular forms, and I would like to use their built-in change detection to implement a functionality in my application. When a user clicks a button, he should only see a dialog if he/she has made any changes in the form.
I have changesMade variable:
private changesMade: boolean;
This is my TS code of the form:
this.carForm = new FormGroup({
name: new FormControl('', [
Validators.required,
Validators.pattern('[a-zA-Z ]*'),
Validators.minLength(1),
Validators.maxLength(10)
])});
This is my HTML code of the form:
<form [formGroup]="carForm">
<ion-item>
<ion-label stacked>car name</ion-label>
<ion-input type="text" [(ngModel)]="carname" formControlName="name"></ion-input>
</ion-item>
</form>
Here is my simulated(for now) service call where I subscribe to form changes after I've set the value of carname, which is bound to the input
setTimeout(()=>{
this.carname = "BMW";
this.carForm.valueChanges.subscribe(val => {
this.changesMade = true;
});
}, 44)
The problem here is that even though I haven't touched the form, this.changesMade gets set to true.
NOTE: If I move the subscribe part of the code in the ngAfterViewInit, it still sets the changesMade to true even though I haven't toushed the input:
ngOnInit(){
//simulated server call
setTimeout(()=>{
this.carname = "BMW";
}, 44)
}
ngAfterViewInit(){
this.carForm.valueChanges.subscribe(val => {
this.changesMade = true;
});
}
I have created a STACKBLITZ demonstrating the problem. How can I make it execute this.changesMade = true;
only when I've actually physically touched the input in the UI?
So by putting the subscription at the end of the callstack (with setTimeout(0)) everything seems to be working as expected:
//simulated server call
setTimeout(()=>{
this.carname = "BMW";
setTimeout(function(){
this.carForm.valueChanges.subscribe(val => {
this.changesMade = true;
});
}.bind(this), 0)
}, 44)
Here is a STACKBLITZ demonstrating that it works.
UPDATE
Since using reactive forms with ngModel is deprecated in Angular 6+, it's better to replace the reactive forms with template driven forms in similar use cases.