1

I've been trying to refactor some Angular code to take advantage of the async pipe and get rid of a bunch of subscriptions in my components, but it ends up looking really messy inside the template when I have to async pipe a ton of references to a Observable<Item> variable instead of assigning it once as an Item.

Is there a way to assign an observable result stream to a variable within the template and then use it as normal? For example, go from this:

    <div *ngIf="item | async">
        <p>{{ (item | async).property1 }}</p>
        <p>{{ (item | async).property2 }}</p>
        <p>{{ (item | async).property3 }}</p>
    </div>

to something like this:

    <div *ngVariableHere="(item | async) as item">
        <p>{{ item.property1 }}</p>
        <p>{{ item.property2 }}</p>
        <p>{{ item.property3 }}</p>
    </div>

Or in a case like this, is it more the 'Angular way' to just subscribe to the observable in the component and assign the resulting value to item?

Many thanks!

mcheah
  • 1,209
  • 11
  • 28
  • 1
    is `item` one object with many properties, or an array of objects? – Marshal Nov 09 '20 at 17:30
  • In this example it's the former. I suppose i could map `item` to it's own single-item array and accomplish this via `*ngFor="let item of (items | async)"` but that seems super icky to me. – mcheah Nov 09 '20 at 17:34

1 Answers1

2

You were close in your second example, try let item instead of as item

<div *ngIf="item | async; let item">
    <p>{{ item.property1 }}</p>
    <p>{{ item.property2 }}</p>
    <p>{{ item.property3 }}</p>
</div>

STACKBLITZ

This is a stackblitz example of using ng-template and passing the object via $implicit

https://stackblitz.com/edit/ng-template-vhp6m4?file=src/app/app.component.html

Here is SO answer used to create example

What is $implicit in angular 2?

Marshal
  • 10,499
  • 2
  • 34
  • 53
  • i love you. What if (for some reason) I didn't want an *ngIf directive there? does defining `let item` need to be an some sort of other structural directive? – mcheah Nov 09 '20 at 18:41
  • 1
    I believe so. Because `*ngIf` becomes `` I am not sure how to decouple the let from the structural directive. Someone may know how, unfortunately I do not – Marshal Nov 09 '20 at 19:30
  • 1
    Interesting. Maybe an empty structural directive can be written that only does template projection. Then it can be used to do the capture variables and transfer them to the on the fly created template instance. https://github.com/angular/angular/blob/16bc0fc3ec7d6eb018059864b3011693740f3fba/packages/common/src/directives/ng_if.ts#L201 – elpddev Nov 09 '20 at 20:26
  • 1
    @elpddev think you are on to something. Updated answer to include stackblitz showing an example of passing the `object` via `$implicit`.. would be a verbose solution to avoid the `*ngIf` but I added to the answer as I found it interesting. – Marshal Nov 09 '20 at 20:58