Angular - How to combine multiple "valueChanges" observables into one
Asked Answered
T

3

18

How can I combine the following subscriptions into one?

    this.form.get("type").valueChanges.subscribe(() => {
        this.calcFinalTransports();
    })
    this.form.get("departure").valueChanges.subscribe(() => {
        this.calcFinalTransports();
    })
    this.form.get("destination").valueChanges.subscribe(() => {
        this.calcFinalTransports();
    })
    this.form.get("stations").valueChanges.subscribe(() => {
        this.calcFinalTransports();
    })
Tuxedo answered 12/12, 2017 at 20:31 Comment(2)
Subscribe to this.form.valueChanges? Or do you mean something more like an Observable.merge? It's not clear.Livvi
@AngularInDepth.com answer is exactly what i need? Why do you downvote? I was very clearTuxedo
N
20

You have a few choices depending on what output you expect. You may want to read this article:

If you just want to get notified whenever any of the value changes use merge:

import {merge} from "rxjs/observable/merge";

merge(
    this.form.get("type").valueChanges,
    this.form.get("departure").valueChanges,
    this.form.get("destination").valueChanges
    this.form.get("stations").valueChanges
).subscribe(() => this.calcFinalTransports());
Nodarse answered 12/12, 2017 at 20:34 Comment(4)
This seems to throw an error in VSCode saying Property 'subscribe' does not exist on type 'UnaryFunction<Observable<{}>, Observable<any>>'.. Has this changed in RxJS5?Border
@mtpultz, I don't know, I suggest you ask another quetsionNodarse
Seems to work if I merge onto an initial observable using a pipe: first$.pipe(merge(second$, third$,...).subscribe(...);Border
The link provided @MaxKoretskyi is no longer valid. This one seems to be the right one.Imputation
C
2

If want to use single Data observable pattern and combine multiple observables into one observable, then combineLatest may come as useful.

PesudoCode

userNameAndEmail$=this.userNameAndEmail().pipe(startsWith(null));
userAddressDetail$=this.userAddressDetails().pipe(startsWith(null));
userMiscDetails$=this.userMiscDtls();


completeUserData$=combineLatest([userNameAndEmail$,userAddressDetail$,userMiscDetails$])
.pipe(map(([userNameAndEmail,userAddressDetail,userMiscDetails])=>{  
 return {userNameAndEmail,userAddressDetail,userMiscDetails};  } ));

However, there are certain conditions. https://www.learnrxjs.io/learn-rxjs/operators/combination/combinelatest

Collaborative answered 10/9, 2020 at 0:45 Comment(0)
A
0

The accepted answer on this related question shows to get the combineLatest to emit when not all of the added observables have emitted a value yet. This works great when your form controls are initialized with values of undefined.

RxJS combineLatest without waiting for source observables to emit?

combineLatest([
  source1$.pipe(startWith(undefined)),
  source2$.pipe(startWith(undefined)),
])
Artur answered 29/6, 2023 at 19:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.