Home > Mobile >  How to merge several valueChanges observable dynamic using RXJS operator
How to merge several valueChanges observable dynamic using RXJS operator

Time:11-30

I have a dynamic form, something like this.

 profileForm = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
    age: new FormControl(''),
    ...
  });

I want to do something when the value changes, so I did:

this.profileForm.valueChanges.subscribe(() => {
           console.log('changed'   this.profileForm.getRawValue());
});

But I don't want every change from the entire form, just from some of the controls, but I can't do this approach:

this.profileForm.controls['firstName'].valueChanges...

because my form is dynamic. so I tried to create an array in my dynamic method, something like that will return this.

controlsTrigger = ['firstname', 'age'];

note that the last name it's should not trigger the console.log.

so I saw the merge operator from rxjs

merge(
    this.form.get("firstname").valueChanges,
    this.form.get("age").valueChanges,
).subscribe(() => console.log('changed'));

But I want to use it with dynamics controls.

CodePudding user response:

If your main problem here is, how to get controlsTrigger into merge, you could use Array.map and the spread-operator:

merge(
  ...controlsTrigger.map(name => this.form.get(name).valueChanges))
).subscribe(() => console.log('changed'));

CodePudding user response:

The problem with merge operator is that you can't tell where the emitted value is coming from so you would have to map the valueChanges and create a relation yourself. So something like this should do the trick:

const controls = ["lastName", "firstName"];

merge(
    ...controls.map(c =>
     this.profileForm.get(c).valueChanges.pipe(map(x => ({ control: c, value: x })))
)).subscribe(console.log);

If you use combineLatest it will emit values in the same order as the passed array of observables. BUT it emits only when each control has emitted at least once, which is not optimal if you are listening to formInputs.

Personally I would prefer subscribing to valueChanges of the whole form and execute logic when the fields you are interested in are included, but its up to you

CodePudding user response:

Maybe you need to use a pipe operator with a combination of combineLatest() and withLatestFrom() ?

combineLatest(this.form.get("fieldThatWillTrigger1").valueChanges, this.form.get("fieldThatWillTrigger2").valueChanges).pipe(withLatestFrom(this.form.get("fieldThatWONTTRIGGER1").valueChanges),withLatestFrom(this.form.get("fieldThatWONTTRIGGER2").valueChanges).subscribe(data => {
dosomethinghere();
});

THe hardpart is making it dynamic so you need to figure that one our

  • Related