Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - Get the value of changed FormControl in Observable

I have a simple Form built with FormBuilder:

this.contactForm = formBuilder.group({
  'name': [''],
  'email': [''],
  'phone': [''],
});

I want to watch every control for changes, and run a function with the updated value when this happens:

getContacts(value: any) {
    this.phoneContacts.findContact(value).then(
        contacts => {
            // do something
        }
    );
}

Right now, I'm doing this for every control, using bind to have access to the this object of the component:

this.contactForm.get('name').valueChanges.subscribe(this.getContacts.bind(this));
this.contactForm.get('email').valueChanges.subscribe(this.getContacts.bind(this));
this.contactForm.get('phone').valueChanges.subscribe(this.getContacts.bind(this));

Is there any way to watch for changes and have the updated value with just one subscription? I know I can subscribe directly to this.contact.form, but then instead of just the updated control I get all controls as the value.

like image 469
Alexandru Pufan Avatar asked Oct 25 '25 07:10

Alexandru Pufan


1 Answers

You can merge the 3 individual observables into one using the merge operator. That will give you a single observable that emits the single value any time any one of the form field values changes.

this.contactForm.get('name').valueChanges
    .merge(this.contactForm.get('email').valueChanges)
    .merge(this.contactForm.get('phone').valueChanges)

The main problem with the approach above is that you now don't know which value goes with which form control. One solution is to map the value changes into another object that contains both the value and the control (i.e. the source of the value)

// making some local variables for convenience
let name = this.contactForm.get('name')
let email = this.contactForm.get('email'
let phone = this.contactForm.get('phone')

name.valueChanges.map(v => ({control: name,value: v})
    .merge(email.valueChanges.map(v => ({control: email, value: v}))
    .merge(phone.valueChanges.map(v => ({control: phone, value: v}))  

This will give an observable that emits whenever any of the fields change, and the value it emits will be an object containing the value and the control that emitted that value.

like image 83
snorkpete Avatar answered Oct 26 '25 22:10

snorkpete



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!