How to handle ngrx let with many subscribes as ng-container inside ng-container?
Asked Answered
C

4

14

I start using ngrx let to using plain objects.

The problem is when I use a lot of observables in my component, I end up with the code which is seems bad (ng-container inside ng-container inside ng-container inside ng-container ...):

<ng-container *ngrxLet="obs1$ as obs1">
 <ng-container *ngrxLet="obs2$ as obs2">
  <ng-container *ngrxLet="obs3$ as obs3">
   <ng-container *ngrxLet="obs4$ as obs4">

    <app-comp [data]="obs1" ..>..</app-comp>
    <app-comp2 [data]="obs1" [data2]="obs3"..>..</app-comp2>
    <app-comp3 [data]="obs1" ..>..</app-comp3>
    <app-comp4 [data]="obs1" ..>..</app-comp4>
    <app-comp5 [data]="obs4" [data11]="obs1" ..>..</app-comp5>
    <app-comp6 [data]="obs2" ..>..</app-comp6>
    <app-comp7 [data]="obs3" ..>..</app-comp7>
  </app-number>
</ng-container>

Is there a better way to handle this syntax?

Catalectic answered 29/10, 2020 at 6:5 Comment(0)
R
6
<ng-container *ngrxLet="{obs1: obs1$, obs2: obs2$, obs3: obs3$} as context">
    <app-comp1 [data]="context.obs1" …>…</app-comp1>
    <app-comp2 [data]="context.obs2" …>…</app-comp2>
    <app-comp3 [data]="context.obs3" …>…</app-comp3>
</ng-container>
Refraction answered 14/6, 2023 at 7:11 Comment(0)
S
3

ngrxLet does not seem to support that feature, you could use combineLatest as mentioned in previous answer or try some trcik i used with *ngIf

<ng-container *ngIf="{
  obs1: obs1$ | async,
  obs2: obs2$ | async,
  obs3: obs3$ | async,
  obs4: obs4$ | async
} as data">
    <app-comp [data]="data.obs1"></app-comp>
    <app-comp2 [data]="data.obs1" [data2]="data.obs3"></app-comp2>
    <app-comp3 [data]="data.obs1"></app-comp3>
    <app-comp4 [data]="data.obs1"></app-comp4>
    <app-comp5 [data]="data.obs4" [data11]="data.obs1"></app-comp5>
    <app-comp6 [data]="data.obs2"></app-comp6>
    <app-comp7 [data]="data.obs3"></app-comp7>
</ng-container>
Satterwhite answered 10/5, 2022 at 6:10 Comment(0)
C
1

You could combine the observables in the controller using RxJS functions like combineLatest, zip and forkJoin. Each has a specific mechanism and you could find the differences between them here.

Illustration using combineLatest

Controller

combined$: Observable<any>;

ngOnInit() {
  this.combined$ = combineLatest(
    obs1$.pipe(startWith(null)),
    obs2$.pipe(startWith(null)),
    obs3$.pipe(startWith(null)),
    obs4$.pipe(startWith(null))
  ).map(([obs1, obs2, obs3, obs4]) => ({  // <-- `map` emits a user-friendly object
    obs1: obs1,
    obs2: obs2,
    obs3: obs3,
    obs4: obs4
  }));
}

Template

<ng-container *ngrxLet="combined$ as data">
  <app-comp [data]="data?.obs1" ..>..</app-comp>
  <app-comp2 [data]="data?.obs1" [data2]="data?.obs3"..>..</app-comp2>
  <app-comp3 [data]="data?.obs1" ..>..</app-comp3>
  <app-comp4 [data]="data?.obs1" ..>..</app-comp4>
  <app-comp5 [data]="data?.obs4" [data11]="data?.obs1" ..>..</app-comp5>
  <app-comp6 [data]="data?.obs2" ..>..</app-comp6>
  <app-comp7 [data]="data?.obs3" ..>..</app-comp7>
</ng-container>

However there is a caveat. combineLatest and zip won't start emitting unless each of the source observable has emitted at least once. We can enforce it using the startWith operator like shown here. But then you need to make sure the first value (null here) doesn't affect the data binding. You could of course replace *ngrxLet with *ngIf to avoid emitting the null, but then you'd lose the benefits of *ngrxLet.

Coccid answered 29/10, 2020 at 6:32 Comment(0)
P
1

The LetDirective allows you to track multiple observable by using a composition.

Extract from the documentation at https://ngrx.io/guide/component/let#combining-multiple-observables

The *ngrxLet directive can be also used with a dictionary of observables. This feature provides the ability to create a view model object in the template:

<ng-container *ngrxLet="{ users: users$, query: query$ } as vm">
  <app-search-bar [query]="vm.query"></app-search-bar>
  <app-user-list [users]="vm.users"></app-user-list>
</ng-container>
Piracy answered 15/5, 2024 at 14:1 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.