2016-12-30 62 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目前不返回可观察的。它可能在未来。 –