簡體   English   中英

Angular 2 如何讓子組件等待異步數據准備就緒

[英]Angular 2 how to make child component wait for async data to be ready

我正在將異步數據從父組件傳遞給子組件。 並且子組件需要知道數據的長度才能執行某些操作。

問題是子組件無法使用“Oninit”鈎子來工作,因為此時數據不可用。 那么我該怎么做呢?

父組件代碼如下所示:

@Component({
    moduleId: module.id,
    selector: 'parent',
    template: `<div>
                    <child [items]="items | async">
                </div>`
})

export class Parent implements OnInit {

    items: Items[];

    constructor(
        private itemService: ItemService,
        private router: Router
    ) { }    

    ngOnInit() {
        this.itemService.getItemss()
            .subscribe(
                items => this.items = items,
                error => this.errorMessage = <any>error
            );
    }

}

子組件看起來像:

@Component({
    moduleId: module.id,
    selector: 'child',    
    template: `<div>
                    <div *ngFor="let itemChunk of itemChunks"></div>
                    content here
                </div>`
})
export class child implements OnInit{
    @Input() items: Items[];
    itemChunks: Items[][];

    ngOnInit() {
        this.itemChunks = this.chunk(this.Items);
    }

    chunk(items: Items[]) {
        let result = [];
        for (var i = 0, len = items.length; i < len; i += 6) { // this line causes the problem since 'items' is undefined
            result.push(items.slice(i, i + 6));
        }
        return result;
    }
}

處理這個問題的最佳做法是什么?

有三種方法可以做到這一點:

  1. 在父*ngIf中放置一個*ngIf 僅在父items准備就緒時渲染子items
<div *ngIf="items">
   <child [items]="items | async">
</div>
  1. 在 child 中分離您的輸入getter setter 然后在設置值時采取行動,您也可以使用 RxJS BehaviorSubject
private _items = new BehaviorSubject<Items[]>([]);

@Input() set items(value: Items[]) { 
    this._items.next(value); 
}

get items() {
   return this._items.getValue();
}

ngOnInit() {
    this._items.subscribe(x => {
       this.chunk(x);
    })
}
  1. 在孩子的ngOnChanges期間執行此ngOnChanges 例如,請參閱此處。 https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges

更簡單的解決方案:

ngOnChanges(changes: SimpleChanges) {
    if (changes['items'].currentValue) {
        this.items = items
    }
}

您可以使用 setter :

export class child implements OnInit{
    itemChunks: Items[][];

    private _items ;

    //bellow  will get called when ever the items are passed in by the parent component
    @Input( 'items' ) set items ( items: Items[] ) {
       this._items = items;

       this.itemChunks = this.chunk(this._items);
    }




    chunk(items: Items[]) {
        let result = [];
        for (var i = 0, len = items.length; i < len; i += 6) { // this line causes the problem since 'items' is undefined
            result.push(items.slice(i, i + 6));
        }
        return result;
    }
}



順便說一句,我覺得你的父組件也不對,應該是:

@Component({
    moduleId: module.id,
    selector: 'parent',
    template: `<div>
                    <child [items]="items | async">
                </div>`
})

export class Parent implements OnInit {

    items: Items[];

    constructor(
        private itemService: ItemService,
        private router: Router
    ) { 
         this.items = this.itemService.getItemss(); // if getItemss is returning an observable, which I think it does
     }    

}

暫無
暫無

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

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