2016-12-30 8 views
8

Przekazuję dane asynchroniczne z komponentu nadrzędnego do komponentu potomnego. A komponent potomny musi znać długość danych, aby coś zrobić.Angular 2, jak sprawić, by komponent potomny oczekiwał na gotowość danych asyn

Problem polega na tym, że komponent potomny nie może korzystać z haka "Oninit" w celu wykonywania pracy, ponieważ dane nie są obecnie dostępne. Więc jak mam to zrobić?

Kod składnikiem dominującym wygląda następująco:

@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 
      ); 
    } 

} 

i składnik dziecko wygląda następująco:

@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; 
    } 
} 

jaka jest najlepsza praktyka, aby sobie z tym poradzić?

Odpowiedz

13

Istnieją trzy sposoby, aby to zrobić:

  1. położyć * ngIf w rodzica. Wykonywanie renderowania tylko wtedy, gdy rodzic jest gotowy items.

    <div *ngIf="items"> 
        <child [items]="items | async"> 
    </div> 
    
  2. oddzielić wejście gettersetter u dziecka. Następnie zadziałaj, gdy tylko ustawisz wartość, możesz również użyć 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. Zrób to podczas ngOnChanges dziecka. Patrz tutaj na przykład. https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges

+0

Skorzystaj z opcji 2. Zachowuje się dokładnie zgodnie z oczekiwaniami. Dziękuję bardzo. –

+0

@Chybie, dzięki za skopiowanie mojej odpowiedzi: d – Milad

+0

@Milad, przepraszam? Nie rozumiem cię. – Chybie

0

Można użyć 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; 
    } 
} 



Wszelkie nawiasem mówiąc, czuję się jak komponent rodzic nie jest w porządku, jak również powinno być :

@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

Dzięki za odpowiedź. Ale itemService w tej chwili nie zwraca możliwości obserwowania. Może w przyszłości. –

Powiązane problemy