2016-01-02 14 views
14

Ho tre componenti: App, Genitori e bambini:@ContentChildren non vengono popolati

App componenti

@Component({ 
    selector: 'app', 
    directives: [Parent,Child], 
    template: '<parent><child>hi</child><child>there</child></parent>' 
}) 
export class AppComponent { 
    constructor() { 
    } 
} 

Parent componente

@Component({ 
    selector: 'parent', 
    template: '<div><h1>Parent</h1><ng-content></ng-content></div>' 
}) 
export class Parent { 
    @ContentChildren(Child) children: QueryList<Child>; 
    ngAfterContentInit() { 
     console.log(this.children); 
    } 
} 

Componente figlio

@Component({ 
    selector: 'child', 
    template: '<div><h1>Child</h1></div>' 
}) 
export class Child { 
} 

Come si può vedere nella componente genitore, ho cercato di usare @ContentChildren per ottenere la lista dei componenti del bambino, utilizzando il tipo Child come selettore. Tuttavia, questo non sembra funzionare - l'elenco dei contenuti dei bambini è sempre indefinito.

Nel metodo ngAfterContentInit(), mi sarei aspettato che i contenuti fossero popolati.

Mi manca qualcosa?

[Update]

Così si scopre che il problema esiste quando tutti e tre i componenti sono nello stesso file (vedi finestra della console di debug in cui l'uscita ho i contenuti figli):

Plnkr Demo of Issue

Se sono in file separati il ​​problema scompare:

Plnkr Demo Working

Normalmente, inserisco tutti i componenti nello stesso file solo a scopo di apprendimento. Ma mi ha incuriosito. Qualcuno sa perché il comportamento è diverso?

+0

I bambini sono visibili nel DOM? L'ho appena provato (in Dart) e funziona. Hai provato un tipo più permissivo di 'QueryList ' per la variabile come 'any'. –

+0

@ GünterZöchbauer Ho provato a cambiare tipo, ma il problema è ancora lì. Sembra che sia correlato a tutti e tre i componenti nello stesso file. – pixelbits

+0

Non riesco a riprodurre in Dart (se questo è un aiuto), funziona anche con tutto in un unico file. –

risposta

20

È necessario utilizzare forwardRef per referenziare classi che non sono ancora definite. Vedi this plunk. Ricorda ES6 classes are not hoisted.

@Component({ 
    selector: 'parent', 
    template: '<div><h1>Parent</h1><ng-content></ng-content></div>' 
}) 
export class Parent { 
    @ContentChildren(forwardRef(() => Child)) children; // <!- HERE 

    ngAfterContentInit() { 
     console.log(this.children); 
     console.log(this.children.length); 
    } 
} 

UPD Mark Rajcok rilevare un eccellente articolo sui riferimenti a termine in angular2 (vedi il commento qui sotto). Da leggere: thoughtram.io Forward references in Angular 2.

+0

Questo spiega perché funziona in Dart. –

+1

+1, battimi sul post. OP, nota che solo [dichiarando 'Child' prima di' Parent'] (http://plnkr.co/edit/64OJMwOwEle6wNycwwDz?p=preview) nello stesso file funziona anche. – drewmoore

+1

Solo per FYI, l'uso di 'forwardRef()' è citato nella [Guida dev di Dependency Injection] (https://angular.io/docs/ts/latest/guide/dependency-injection.html), nella parte inferiore della pagina, nella sezione "Appendice: Perché consigliamo una classe per file". La guida consiglia inoltre di leggere [questo post del blog] (http://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html) per maggiori informazioni su quando utilizzare 'forwardRef() '. –

Problemi correlati