I'm trying to inject a parent component into a child component. I thought this would be straightforward – simply specify/inject the parent component in the child's constructor()
:
constructor(private _parent:AppComponent) {} // child component constructor
I get the following error:
EXCEPTION: Cannot resolve all parameters for ChildComponent(?). Make sure they all have valid type or annotations.
What am I missing?
ChildComponent:
import {Component} from 'angular2/core';
import {AppComponent} from './app.component';
@Component({
selector: 'child',
template: `<p>child</p>`
})
export class ChildComponent {
constructor(private _parent:AppComponent) {}
}
AppComponent:
import {Component} from 'angular2/core';
import {ChildComponent} from './child.component';
@Component({
selector: 'my-app',
template: `{{title}} <child></child>
`,
directives: [ChildComponent]
})
export class AppComponent {
title = "Angular 2 - inject parent";
constructor() { console.clear(); }
}
Best Answer
See @EricMartinez's comment for the answer. The problem seems to be a circular reference when A imports B and B imports A.
Here's a plunker that uses two files instead of the one file that is in Eric's plunker.
The only change from my original plunker is in the ChildComponent:
I don't know for sure if this eliminates the circular reference, since A and B are still importing each other, but it seems to work.
See also https://github.com/angular/angular/issues/3216, where Miško states:
Hmm... the reason I tried injecting the parent was because I see two ways for a child to communicate with a parent:
And I was trying to determine when to use each approach. Miško makes it sound like 2. should be rare.
Update: I was thinking about this some more... 1. is better because there is less coupling between the child and the parent. With 1. the child doesn't need to know (and probably shouldn't know) the public API/interface of the parent.
In the reverse direction (e.g., the parent uses
@ViewChild
(@Query
is now deprecated) to get a reference to the child, then calls methods on the child), the coupling is fine, because the parent is using the child component, so it needs to know the public API/interface of the child: i.e., the input and output properties and public methods.