Combine two or more (boolean) observables on single ngIf using async pipe

Sebastian picture Sebastian · Sep 7, 2017 · Viewed 10.8k times · Source

Without observables I can write the following line in the HTML template:

<div *ngIf="(myVarA || myVarB) && myVarC !== x"></div>

How do I translate this line if all myVar variables are now actually observables?

<div *ngIf="((myVarA | async) || (myVarB | async)) && (myVarC | async) !== x">

does not work.

In another question (Putting two async subscriptions in one Angular *ngIf statement) the possibility to combine two or more observables into one ngIf can be achieved like

<div *ngIf="{ a: myVarA | async, b: myVarB | async } as result"></div>

However, I do not see the possibility to use any boolean operators (or any operators for that matter) on the expression that is then being used to evaluate the ngIf.

How can I tackle this issue? Please note, all my Observables use a BehaviorSubject underneath. I think essentially what I want is to use the combineLatest operator inside the template.

Bonus: Is there any way to extract the single value of myVarA if the whole expression evaluates to true for later use in the template (as in myVarA | async as varA)?

Answer

Jota.Toledo picture Jota.Toledo · Sep 7, 2017

What about using combineLatest?

For example:

import { combineLatest } from 'rxjs/observable/combineLatest';
import { Observable } from 'rxjs/Observable';    

@Component({...})
export class FooComponent {
  obs1$: Observable<bolean>;
  obs2$: Observable<bolean>;
  obs3$: Observable<bolean>;

  constructor(){
    // set observables
  }

  get combined$(){
    return combineLatest(
      this.obs1$,
      this.obs2$
      this.obs3$,
      (one,two,three)=>(one || two) && three);
  }
}

// template
<div *ngIf="combined$ | async">

Check the following fiddle for guidance:

https://jsfiddle.net/uehasmb6/11/

More info about the combineLatest operator here

UPDATE: But if you still want to keep all that logic inside of the template, you could try something like:

<div *ngIf="((myVarA | async) || (myVarB | async)) && ((myVarC | async) !== x)">

But I would advice you against this. Keeping the HTML template as clean as possible is a good practice.