I have three components: App, Parent, and Child:
App Component
@Component({ selector: 'app', directives: [Parent,Child], template: '<parent><child>hi</child><child>there</child></parent>' }) export class AppComponent { constructor() { } }
Parent Component
@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); } }
Child Component
@Component({ selector: 'child', template: '<div><h1>Child</h1></div>' }) export class Child { }
As you can see in the Parent component, I've tried to use @ContentChildren
to get the list of Child components, using the Child
type as a selector. However, this does not seem to work - the content children list is always undefined.
In the ngAfterContentInit()
method, I would have expected content children to be populated.
Am I missing something?
[Update]
So it turns out that the problem exists when all three components are in the same file (see console debug window where I output the content children):
Plnkr Demo of Issue
If they are in separate files the problem goes away:
Plnkr Demo Working
Normally, I would only place all the components in the same file for learning purposes. But it has me curious. Does anyone know why the behaviour is different?
You need to use forwardRef to reference classes which are not yet defined. See this plunk. Remember 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 pointed out an excellent article about forward references in angular2 (see the comment bellow). Must read: thoughtram.io Forward references in Angular 2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With