Async pipe does not fill object data into template

后端 未结 5 1253
遇见更好的自我
遇见更好的自我 2021-02-01 17:41

Can anyone help me see if there is a syntax error here in my template? It does not give error, but does not fill in data into the template either:

相关标签:
5条回答
  • 2021-02-01 18:06

    Objects are a bit tricky with the async pipe. With an Observable that contains an array, we can use NgFor and create a local template variable (hero below) that gets assigned each item of the array after the async pipe extracts the array from the Observable. We can then use that variable elsewhere in the template:

    <div *ngFor="let hero of heroes | async">
      {{hero.name}}
    </div>
    <!-- we can't use hero here, outside the NgFor div -->
    

    But with an Observable that contains a single object, I'm not aware of any way to create a local template variable that will reference that object. Instead, we need to do something more complicated:

    <div>{{(hero | async)?.name}}</div>
    

    And we would need to repeat that for each property of the object we want to display. (The above line assumes that component property hero is an Observable.)

    It is probably easier to assign the object (that is inside the Observable, hero$ below) to a property of the component, using component logic:

    this._heroService.hero$.subscribe(data => this.hero = data.json());
    

    and then use NgIf or the Elvis/safe navigation operator to display the data in the view:

    <div *ngIf="hero">{{hero.name}}</div>
    <!-- or -->
    <div>{{hero?.name}}</div>
    
    0 讨论(0)
  • 2021-02-01 18:07

    Another option would be to use @Input and leverage smart/dumb component approach. In your smart component you can pass the async object to the dumb component then in the dumb component you can use it like a normal object.

    The idea is that your smart component deals with logic and data and the dumb component handles presentation.

    Smart component:

    <dumb-component [myHero]="hero$ | async"></dumb-component>
    

    Dumb component class:

    @Input() myHero: Hero;
    

    Dumb component template:

    <div>{{ myHero.name }}</div>
    
    0 讨论(0)
  • 2021-02-01 18:19

    The best way to handle a Single Observable Object inside an Angular 2.3.x, or Angular 4.x template is to use an async pipe with a template variable.

    Here's a common goal for angular developers. Take an array of elements from redux, and pluck a single matching element from the collection. Then render that singular object in a template.

    COMPONENT

    @Component({
      selector: 'app-document-view',
      templateUrl: './document-view.component.html',
      styleUrls: ['./document-view.component.scss']
    })
    export class DocumentViewComponent implements OnInit {
    
      @select(['documents', 'items']) readonly documenList$: Observable<DocumentDTO[]>;
      public documentVO$: Observable<DocumentDTO>;
    
      constructor(private _state: NgRedux<IAppState>,
                  private _route: ActivatedRoute,
                  private _documentActions: DocumentActions) {
    
        _route.params.subscribe(params => {
          let modelId: number = parseInt(params['modelId']); //1          
          let documentId: number = parseInt(params['documentId']); //50
          this._documentActions.getDocument(modelId, documentId);
        });
      }
    
      ngOnInit() {
    
        //documenList holds all of the documents in our application state
        //but this view only wants a single element
    
        this.documentVO$ = this.documenList$.map(documents => documents.find(doc => doc.documentId === 50));
      }
    }
    

    VIEW

    <div class="row" *ngIf="documentVO$ | async as dto">
        <div id="about" class="col-12">
            <div id="title" class="paper meta">
                <p>{{ dto.title }}</p>
            </div>
        </div>
    </div>
    
    0 讨论(0)
  • 2021-02-01 18:26

    This is now possible using the 'as' syntax, available in v4.0.0:

    <span *ngIf="user$ | async as user; else loadingUserInfo">
     {{user.firstName}} {{user.lastName}}
    </span>
    <ng-template #loadingUserInfo>
      Loading user information...
    </ng-template>
    

    More details available in the RFC thread on github.

    0 讨论(0)
  • 2021-02-01 18:26

    I am just adding a precision on how to use the smart / dumb component approach in the case you need to use the async pipe and a bracket syntax.

    That combine a trick found here.

    < ui-gallery-image([image]="(imagesFB | async) ? (imagesFB | async)[0] : null") ></ui-gallery-image>

    I've spend hours to find. Hope this help. More info on this blog post.

    0 讨论(0)
提交回复
热议问题