Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Angular 2 render HTML template after a promise in the component is resolved?

For my app, the ItemDetailComponent is where info of an item will be displayed. I have a service that retrieves all items using promise. I use ActivatedRoute to retrieve the item ID from the url path, then run the service, get all items, then find the item with the ID retrieved above, and assign it to selectedItem variable.

Here is item-detail.component.ts:

export class ItemDetailComponent implements OnInit {
  private title = 'Item Details'
  private selectedItem: object

  constructor(
    private route: ActivatedRoute,
    private itemService: ItemService
  ) {}

  ngOnInit() {
    const selectedItemId = this.route.snapshot.params.itemId

    return this.itemService.getAllItems()
      .then((items) => {
        return _.find(items, item => item.itemId === selectedItemId)
      })
      .then((selectedItem) => {
        this.selectedItem = selectedItem
        console.log('Inside promise', this.selectedItem)
      })
    console.log('Outside promise', this.selectedItem)
  }
}

And here is item-detail.component.html template so I could display my item, just an example:

<div>
  <h1>{{title}}</h1>

  <div *ngIf="selectedItem">
  <div><label>Item ID: </label>{{selectedItem.itemId}}</div>
  </div>
</div>

The app returns nothing but the title unfortunately. I then added the two console.log() commands and found out that the one outside of the promise as well as the html template are rendered before the promise is fulfilled, and no selectedItem is available at that time. How could I force the app to execute them only after the promise is resolved in order to have the selectedItem in place for displayed?

EDIT: I added a new line in the html template to examine further:

<div>
  <h1>{{title}}</h1>
  <div><label>Item ID 1: </label>{{selectedItem.itemId}}</div>
  <div *ngIf="selectedItem">
  <div><label>Item ID 2: </label>{{selectedItem.itemId}}</div>
  </div>
</div>

The app displays "Item ID 1:" label but with no actual id there. The console shows me an error saying that "Cannot read property 'itemId' of undefined", again confirming that the whole template is rendered before promise resolved and is not re-rendered after data is loaded. So weird.

like image 473
Duc Avatar asked Aug 17 '17 09:08

Duc


1 Answers

You could create a Resolver for the route that fetches the desired data.

https://angular.io/api/router/Resolve

https://blog.thoughtram.io/angular/2016/10/10/resolving-route-data-in-angular-2.html

like image 102
heldt Avatar answered Nov 15 '22 05:11

heldt