3

I have a stepper which is conditioned by a single observable

<ng-container *ngIf="!(categoriesLoading$ | async); else loading">
  <mat-vertical-stepper *ngIf="categories$ | async as categories">
    <mat-step>
      <categories-form [categories]="categories"></categories-form>
    </mat-step>
  </mat-vertical-stepper>
</ng-container>

now I would like to add the conditioning of another observable qualifications$

Something like that:

<ng-container *ngIf="!(categoriesLoading$ | async); else loading">
  <mat-vertical-stepper *ngIf="categories$ | async as categories">
    <mat-step>
      <categories-form [categories]="categories"></categories-form>
    </mat-step>
    <mat-step>
      <qualifications-form [qualifications]="qualifications"></qualifications-form>
    </mat-step>
  </mat-vertical-stepper>
</ng-container>

in the controller:

categories$: Observable<Array<Category>>;
categoriesLoading$: Observable<boolean>;
qualifications$: Observable<Array<Qualification>>;
qualificationsLoading$: Observable<boolean>;

how can I do this properly?

Liam
  • 27,717
  • 28
  • 128
  • 190
Mouad Ennaciri
  • 1,217
  • 3
  • 15
  • 28
  • something like this? - I'm not quite sure what you mean: `*ngIf="!(categoriesLoading$ | async) && (qualificationsLoading$ | async); else loading"` Are you looking to extend the condition on line 1? or extending the for loop of line 2? (2nd example) – Jonas Praem Feb 26 '19 at 09:42
  • @JonasPraem I would like to have the same result of the first example by adding `qualifications$` observable – Mouad Ennaciri Feb 26 '19 at 09:47
  • 2
    I would rethink the design of that.. you might run into race conditions. I would chain those observables with .pipe(), then wait for the final one to resolve and act upon that final result, not on 2 at the same time. – chriszichrisz Feb 26 '19 at 09:53
  • 2
    https://stackoverflow.com/questions/44855599/putting-two-async-subscriptions-in-one-angular-ngif-statement/44902848#44902848 – yurzui Feb 26 '19 at 12:48

1 Answers1

3

You can have a look at the Rxjs zip combination operator which might help you.

https://www.learnrxjs.io/operators/combination/zip.html

https://rxmarbles.com/#zip

In your controller, you can create a new observable like:

combined$: Observable<{ categories: Array<Category>, qualifications: Array<Qualification>}> = zip(
    this.categories$,
    this.qualifications$,
    (categories: Array<Category>, qualifications:Array<Qualification>) => { 
        return { categories, qualifications };
    }
);

Which will combine the emitted values, then you can use it to get the combined values:

<ng-container *ngIf="!(categoriesLoading$ | async); else loading">
  <mat-vertical-stepper *ngIf="combined$ | async as combined">
    <mat-step>
      <categories-form [categories]="combined.categories"></categories-form>
    </mat-step>
    <mat-step>
      <qualifications-form [qualifications]="combined.qualifications"></qualifications-form>
    </mat-step>
  </mat-vertical-stepper>
</ng-container>

Also you can use zip to have your loading observables wait for each other:

combinedLoading$: Observable<boolean> = zip(
    this.categoriesLoading$,
    this.qualificationsLoading$,
    (categoriesLoading: boolean, qualificationsLoading: boolean) => { 
        return categoriesLoading && qualificationsLoading;
    }
);
Rauks
  • 313
  • 3
  • 7
  • I have this error: `Type 'OperatorFunction' is missing the following properties from type 'Observable': _isScalar, source, operator, lift, and 6 more.` where do you come from? – Mouad Ennaciri Feb 26 '19 at 14:01