Reputation: 3209
I am using reactive forms in Angular 7.
I have many fields that are dependent on other fields.
What I am curious about of what should I use (change)
or this.form.get("control_name").valueChanges
?
For ex. if both will work on inputs then I want to know difference, pros & cons between them.
Which is better with performance?
Upvotes: 23
Views: 67689
Reputation: 923
In case of an input (text) field, I would suggest to use either valueChanges
or value
depending on your use case:
valueChanges
.change
.This is just a rule of thumb, though, the devil is in the details.
Here is the code of a working example which I wrote while doing my own research/testing, it implements both approaches for the sake of comparison:
Upvotes: 1
Reputation: 1210
I would recommend to use Reactive Forms logic only. If you need to have a behaviour like (change)
has, so that the value should only be emitted when blur is executed, you can set updateOn: 'blur'
like this:
this.fb.group({
title: this.fb.control('', { updateOn: 'blur' }),
description: '',
})
or like this for the whole form:
this.fb.group({
title: '',
description: '',
},{updateOn: 'blur'})
Now you can subscribe to valueChanges:
this.form.valueChanges.subscribe(change=>{ console.log(change) })
In the first example, this will log changes in description every time you type something and for title only on leaving the input field.
Upvotes: 9
Reputation: 335
This is case-to-case, but I find that things like checkboxes and radio buttons (true/false type controls) work better with the (change) handler and inputs and textfields are generally more suitable for valueChanges.
Although I'm not sure of performance, I assume this would be the ideal use case when dealing with this decision.
A good use case for valueChanges (for everything) is a complex form with a lot of ngIf logic. Sometimes these forms need a "chain reaction" of value changes to work correctly, in which case a (change) handler would be useless
Upvotes: 3
Reputation: 39442
Let's just consider that what you're looking for is to listen to a change on an input
tag of type="text"
valueChanges
Since it is an Observable, it will fire with a new value. This value will be the changed value of the input
field. And to listen to it, you will have to subscribe
to the valueChanges
Observable. Something like this:
this.form1.controls['name'].valueChanges.subscribe(change => {
console.log(change); // Value inside the input field as soon as it changes
});
(change)
eventIn case of the change
event, for input
tag, the change
event will only fire once you blur
away from that input
field. Also, in this case, you'll get the $event
Object. And from that $event
Object, you'll have to extract the field value.
So in code, this will look something like this:
import { Component } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
@Component({...})
export class AppComponent {
name = 'Angular';
form1: FormGroup;
form2: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.form1 = this.fb.group({
name: [],
email: []
});
this.form2 = this.fb.group({
name: [],
email: []
});
this.form1.controls['name'].valueChanges.subscribe(change => {
console.log(change);
});
}
onForm2NameChange({ target }) {
console.log(target.value);
}
}
And in the Template:
<form [formGroup]="form1">
<input type="text" formControlName="name">
<input type="text" formControlName="email">
</form>
<hr>
<form [formGroup]="form2">
<input type="text" formControlName="name" (change)="onForm2NameChange($event)">
<input type="text" formControlName="email">
</form>
Here's a Working Sample StackBlitz for your ref.
NOTE: It completely depends on your use case as to which one would be more suitable.
For your specific use case, I would suggest using RxJS Operators to get the job done. Something like this:
zipCodeFormControl
.valueChanges
.pipe(
debounceTime(500),
distinctUntilChanged(),
switchMap(
zipcode => getAddressFromZipcode(zipcode)
),
map(res => res.actualResult)
)
.subscribe(addressComponents => {
// Here you can extract the specific Address Components
// that you want to auto fill in your form and call the patchValue method on your form or the controls individually
});
Upvotes: 44