2016-12-30 71 views
8

我將異步數據從父組件傳遞到子組件。而子組件需要知道數據的長度才能做某件事。Angular 2如何讓子組件等待異步數據準備就緒

問題是這樣的,問題在於此時數據不可用,子組件無法使用'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; 
    } 
} 

什麼是處理這個最好的做法?

回答

13

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

  1. 把一個* ngIf父。只有在父母的items準備好時才提供孩子。

    <div *ngIf="items"> 
        <child [items]="items | async"> 
    </div> 
    
  2. 獨立的輸入孩子gettersetter。然後,只要設置了值,您也可以使用RxJs BehaviourSubject

    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); 
        }) 
    } 
    
  3. 孩子的ngOnChanges時就這樣做。例如參考這裏。 https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges

+0

結束採取選項2.行爲完全如預期。非常感謝。 –

+0

@Chybie,感謝您複製我的答案:d – Milad

+0

@Milad,對不起?我不明白你。 – Chybie

0

您可以使用一個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 
    }  

} 
+0

感謝您的回答。但itemService目前不返回可觀察的。它可能在未來。 –