Reputation: 293
Before I begin please note that I originally asked this question as a feature request at the angular2 github site. However the request was closed and I was advised to post it here. Here I am just repeating my initial request. However you can find some discussion by following the link: https://github.com/angular/angular/issues/10448
I need the ability to obtain a reference to the parent component generically without the child having to know the type of the parent component. Basically I need something like this (pseudocode):
@Component({
template: '<child></child>'
directives: [Child]
})
class ParentComponent{}
@Component({ selector: 'child' })
class ChildComponent{
constructor(@Parent() _parent: any){}
}
Basically I need the _parent
field of the ChildComponent
to reference the ParentComponent
. But notice how the type of _parent
is any
. It's any
because it can be any, literally. ChildComponent
is a generic component that can be used by any type of other component. I know there are solutions out there for this problem but they all entail the child knowing the type of the parent. It goes something like this:
@Component({ selector: 'child' })
class ChildComponent{
constructor(_parent: ParentComponent){}
}
But again, this will not work for me because ChildComponent
can be used in any type of other component, and neither one knows the type of the other. So what I need is some generic way to inject into ChildComponent
its parent component, as set in the component tree, without ChildComponent
knowing the parent type. Does anyone know how I can accomplish this?
Upvotes: 12
Views: 15498
Reputation: 55443
You can use Injector API for the same.
For Angular2 latest release and older versions:
import { Injector } from '@angular/core';
import {AppComponent} from "./app.component";
@Component({ selector: 'child' })
class ChildComponent{
constructor(private inj:Injector){
let parentComponent = this.inj.get(AppComponent);
console.log(parentComponent);
}
}
Upvotes: 19
Reputation: 7242
Here is how to make it work.
@Component({
selector: 'child'
})
class ChildComponent{
constructor( @Optional() public myParent: ParentComponent ){}
}
You can find more info in Angular DI docs
Upvotes: 2
Reputation: 293
Thanks to @yurzui for leading me in the right direction... In the end I found a couple of different ways... unfortunately all involve accessing private members which is less than ideal... If anyone knows of a better way, please speak up... thank you
constructor(private vcRef: ViewContainerRef){
var parentComponent1 = this.vcRef.injector._view.context;
console.log(parentComponent1);
var parentComponent2 = this.vcRef._element.parentView.context;
console.log(parentComponent2);
console.log(parentComponent1 === parentComponent2);
}
Upvotes: 4
Reputation: 101
Using @Input
and a little trick to send the this
of the parent to the child. I guess you can do it the other way around also, to access child from parent via an @Output
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: '<app-child [parnt]="var2"></app-child>',
style: ''
})
export class AppComponent {
title = 'app works!';
var1 = "val1";
var2 = this;
}
import { Component, Input, EventEmitter, OnInit } from '@angular/core';
@Component({
selector: 'app-child',
template: '{{parnt.var1}}',
style: ''
})
export class ChildComponent implements OnInit {
@Input() parnt;
}
You should see "val1" printed, the value of the var1 of the parent printed in the child template.
Upvotes: 8