Subscribe multiple FormControl(s) only once

2020-06-13 10:57发布

问题:

I have filtered out few FormControl(s) from a large FormGroup based on some logic now - I'd like to know how can I merge / combine those selected FormControls and have only one subscribe..

I looked into RxJS docs and marble diagrams but didn't understand it properly. It's very confusing to understand all of these and know which one to use for my case:

- forkJoin
- combineLatest
- merge
- join
- zip

Here's more detailed info about the question:

Let's say 2 FormControls (i.e., controlA, controlB). I want to execute my some handlerFunction whenever any of the FormControl value changes. * It needs to execute my handlerFunction once whenever any control valueChanges (In my case any one control will be changed at one time)

Thanks.

回答1:

The best option for you is combineLatest that emits after all source Observables emitted at least one value and then on every emission from any source Observable:

Observable.combineLatest(controlA.valueChanges, controlB.valueChanges)
  .subscribe(...);

Eventually you can chain each source with startWith(null) to guarantee that every source will emit one item immediately and filter what you want in the subscriber.

Observable.combineLatest(
    controlA.valueChanges.startWith(null),
    controlB.valueChanges.startWith(null)
  )
  .subscribe(([val1, val2]) => ...);

Btw, about the other operators:

  • zip - emits only when all sources emitted the same number of items
  • forkJoin - emits when all sources emitted at least one item and completed (never happens with valueChanges)
  • merge - just merges Observables but you can't know which one emitted what value
  • join - I don't think that's part RxJS 5


回答2:

For those getting combineLatest as deprecated, try combining the valueChanges observables in an array. Also, for those getting startWith as deprecated, try not using null.

combineLatest([
    this.typeSelected.valueChanges.pipe(startWith('')),
    this.checkedFC.valueChanges.pipe(startWith(false))
  ]
).subscribe(([type, checked]) => {
   console.log([type, checked]);
});