In Angular 2, a child component can get its parent component injected through a constructor parameter. Example:
@Component({...})
export class ParentComponen
This post has been solved thanks to Günther. However, I would like to follow up based on the architectural feedback I got.
First and foremost: I completely agree that the TreeNodeComponent use case example is an anti pattern. A data driven component like a tree this should be controlled by data binding. My apologies for this anti pattern.
However, my actual use case (which is more complex to explain) is that I want to develop an advanced dropdown menu. Requirements:
A usage example:
<dropdown label="Actions">
<dropdown-item label="Action 1" (click)="action1()"></dropdown-item>
<dropdown-item label="Action 2" (click)="action2()"></dropdown-item>
<dropdown-item label="Submenu">
<dropdown-item label="Action 3.1" (click)="action31()"></dropdown-item>
<dropdown-item label="Action 3.2">
<dropdown-slider (change)="changeHandler()"></dropdown-slider>
</dropdown-item>
<dropdown-item label="Submenu">
<dropdown-item label="Action 3.3.1" (click)="action331()"></dropdown-item>
<dropdown-item label="Action 3.3.2" (click)="action332()"></dropdown-item>
</dropdown-item>
</dropdown-item>
</dropdown>
My consideration is that this would be hard to implement using data binding. It's much practical to be able to bind event handlers and include custom components this way.
But I might be wrong! Any opinions about this are highly welcome!
This way it's working
constructor(@SkipSelf() @Host() @Optional() parent: TreeNodeComponent) {}
Plunker
@SkipSelf()
is to not get oneself injected which would apply if TreeNodeComponent
is requested@Host()
don't look further up than the host element@Optional()
?? there is no parent TreeNodeComponent
for the root nodeSee also http://blog.thoughtram.io/angular/2015/08/20/host-and-visibility-in-angular-2-dependency-injection.html
Angular2 looks into the current injector for a provider. In your case, TreeNodeComponent corresponds to the component itself.
The parent component instance is located into the parent injector.
I think that you could try to inject an Injector class to have access to the parent injector and then get the instance of the parent component. Something like that:
@Component({
(...)
})
export class TreeNodeComponent {
constructor(injector:Injector) {
let parentInjector = injector.parent;
let parent = patentInjector.get(TreeNodeComponent);
}
}
See this link for the documentation of the Injector class:
That said, I think that the Gunter's comment about binding and shared service is particularly relevant...