I have got simple situation. There is a html form with two fields:
- firstName
- lastName
I want lastName to change for something when user changes firstName. I implemented it through valueChanges observable in Angular (8).
Besides I have two subscription to listen and log changes:
- one on whole form
- one on
lastName
Here is how it is implemented:
ngOnInit(){
this.form = new FormGroup({
firstName: new FormControl('', {updateOn: 'blur'}),
lastName: new FormControl('', {updateOn: 'blur'}),
});
this.form.get('lastName').valueChanges.subscribe(value => console.log('lastName', value));
this.form.valueChanges.subscribe(value => console.log('Value', value));
this.form.get('firstName').valueChanges
.subscribe(firstName => {
this.form.get('lastName').setValue(`firstName ${firstName} ${new Date().getMilliseconds()}`);
});
}
In general - from a user point of view - this behaves as expected. User changes firstName and then lastName changes itself.
But when I look at the console log, here is what I've got:
lastName firstName test 850
Value > {firstName: "test", lastName: "firstName test 850"}
Value > {firstName: "test", lastName: "firstName test 850"}
I expected two logs from whole, but one with first name changed, and second with lastName changed. Something more like this:
Value > {firstName: "test", lastName: ""}
lastName firstName test 850
Value > {firstName: "test", lastName: "firstName test 850"}
Here is a whole example on stackblitz.
Ok, so when I changed a way I update lastName from this:
this.form.get('lastName').setValue(`firstName ${firstName} ${new Date().getMilliseconds()}`);
to this:
setTimeout(() => this.form.get('lastName').setValue(`firstName ${firstName} ${new Date().getMilliseconds()}`));
then logs are in order which I expected:
Value > {firstName: "test", lastName: ""}
lastName firstName test 850
Value > {firstName: "test", lastName: "firstName test 850"}
However, setTimeout seems to be tricky hack here.
Here is whole code on stackblitz.
The question is: What is going on here? Why FormGroups works in that way? Is there a pattern to process such events in Angular (when one form affects another)?