簡體   English   中英

解決組件中的承諾后,如何使Angular 2呈現HTML模板?

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

對於我的應用程序, ItemDetailComponent是將顯示項目信息的位置。 我有一項使用諾言檢索所有項目的服務。 我使用ActivatedRoute從url路徑中檢索項目ID,然后運行服務,獲取所有項目,然后查找具有上面檢索的ID的項目,並將其分配給selectedItem變量。

這是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)
  }
}

這是item-detail.component.html模板,因此我可以顯示我的項目,僅作為示例:

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

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

不幸的是,該應用僅返回標題。 然后,我添加了兩個console.log()命令,發現在諾言實現之前,已呈現了諾言之外的一個以及html模板,並且那時沒有selectedItem可用。 我如何強制應用程序僅在兌現諾言之后執行它們,以使selectedItem可以顯示?

編輯 :我在html模板中添加了新行以進一步檢查:

<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>

該應用程序顯示“項目ID 1:”標簽,但那里沒有實際ID。 控制台顯示了一個錯誤消息,提示“無法讀取未定義的屬性'itemId'”,再次確認整個模板在Promise解決之前已呈現,並且在加載數據后未重新呈現。 太奇怪了。

在您的課程中添加一個布爾變量,例如

private dataAvailable:boolean = false;

並在對promise的訂閱中,當數據可用時將其設為true

then((selectedItem) => {
        this.selectedItem = selectedItem;
this.dataAvailable=true;
        console.log('Inside promise', this.selectedItem)
      })

當數據可用時在模板中呈現

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

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

它應該可以解決問題

更新資料

ngOnInit()似乎只是事件處理程序的鈎子-返回任何內容都不會影響它。 因此,我的舊答案將不起作用。

還有其他解決方法,例如使用* ngIf或將其放在路由等中,但是我希望有諸如resolvePromise(): Promise那樣的東西resolvePromise(): Promise鈎子可以在渲染之前為分辨率設置條件。

這不是開發人員在每個組件中放置樣板。

舊答案

最有可能是因為你缺少return語句在第二then

then((selectedItem) => { this.selectedItem = selectedItem console.log(): return selectedItem;// }

組件樹上方某處是否可能將ChangeDetection設置為OnPush 在這種情況下,模板不會自動重新呈現,因為沒有任何東西觸發此組件的ChangeDetection

查找具有設置changeDetection: ChangeDetectionStrategy.OnPush的Component changeDetection: ChangeDetectionStrategy.OnPush

@Component({
    selector: 'example',
    template: `...`,
    styles: [`...`],
    changeDetection: ChangeDetectionStrategy.OnPush
})

另外,通過使用Resolver您已經有了有效的解決方案,可以檢查是否有幫助:

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

    constructor(
        private route: ActivatedRoute,
        private itemService: ItemService,
        // the reference to the components changeDetector is needed.
        private changeDetectorRef: ChangeDetectorRef 
    ) {}

    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
            // this triggers the changedetection and the template should be rerendered;
            this.changeDetectorRef.detectChanges(); 
            console.log('Inside promise', this.selectedItem)
        });
        console.log('Outside promise', this.selectedItem)
    }
}

這是一篇關於Angulars ChangeDetection的好文章: https ://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM