Angular2: Sum two Observable<number> values

I have a service with two different functions that get the number of itens inside an array that is watched by an BehaviorSubject.

 private itemsInCartSubject: BehaviorSubject<any[]> = new BehaviorSubject([]);
private itemsInCart: any[] = [];

private packetsInCartSubject: BehaviorSubject<Pacote[]> = new BehaviorSubject([]);
private packetsInCart: Pacote[] = [];

 public getTotalItens(): Observable<number> {        

    return this.itemsInCartSubject.map((items: any[]) => {
        return items.reduce((prev, curr: any) => {               
                return prev + Number(curr.qtd);                
        }, 0);
    });
};

   public getTotalPacotes(): Observable<number> {
    return this.packetsInCartSubject.map((items: any[]) => {
        return items.reduce((prev, curr: any) => {               
                return prev + Number(1);                
        }, 0);
    });
};

Inside my component I have two methods to get these numbers:

 public countItens(): Observable<number> {
    return this.cartService.getTotalItens();
}

public countPacotes(): Observable<number> {
    return this.cartService.getTotalPacotes();
}

In my html I can show the values like this:

<p>You have {{countItens() | async}} in your cart</p>

It works fine, updating the values when theres is a change on the subject, but I need to sum the two values of the two Observables.

How can I accomplish that?

I've tried

this.cartService.getTotalItens()+this.cartService.getTotalPacotes();

But it generates the error: Operator '+' cannot be applied to types Observable and Observable

Upvotes: 4

Views: 3260

Answers (1)

Teddy Sterne
Teddy Sterne

Reputation: 14221

You can combine these Observables using combineLatest and then return a new value that is the sum of both. You can add a new function like this:

public getTotal(): Observable<number> {
    return this.countItens()
               .combineLatest(this.countPacotes(), (itens, pacotes) => itens + pacotes);
}

And then in the template you can use it like so:

<p>Total is: {{getTotal() | async}}</p>
Demo of combineLatest

Upvotes: 6

Related Questions