I have three nested components, called level0
, level1
and level2
, defined like so:
@Component({
selector: 'level2',
template: `<div>I am level 2</div>`,
})
export class Level2 {
getName(){
return "my name is 'TWO'";
}
}
@Component({
selector: 'level1',
template: `<div>I am level 1<level2></level2></div>`,
directives: [Level2]
})
export class Level1 {
getName(){
return "my name is 'ONE'";
}
}
@Component({
selector: 'level0',
template: `<div>I am level 0<level1></level1></div>`,
directives: [Level1,Level2]
})
export class App {
@ViewChild(Level1) level1:Level1;
@ViewChild(Level2) level2:Level2;
ngAfterViewInit() {
if(this.level1){var name1 = this.level1.getName();}
if(this.level2){var name2 = this.level2.getName();}
console.log("name1",name1);
console.log("name2",name2);
}
}
In the console, I expected to see:
name1 my name is 'ONE'
name2 my name is 'TWO'
But I see instead:
name1 my name is 'ONE'
name2 undefined
What am I missing? Why can't the Level0
component access Level2
through @ViewChild
?
Is there a way to access the Level2
methods in Level0
?
Here is the plnkr
ViewChild is used to select an element from component's template while ContentChild is used to select projected content.
Working with @ViewChildren is similar to @ViewChild, but the difference between the two is @ViewChildren provides a list of element references rather than returning a single reference. It is used to reference multiple elements. We can then iterate the list of the element referenced by the variable.
If you wish to gain access to a DOM element, directive or component from a parent component class then you rely on Angular ViewChild. When you run ViewChild in Angular, it will return the 1st element that matches. It will match against the template reference selector, directive or component.
It can be acheived if you use ViewChild at each level of your nested components, like this way:
// Level 2
@Component({
selector: 'level2',
template: `<div>I am level 2</div>`,
})
export class Level2 {
getName(){
return "my name is 'TWO'";
}
}
// Level 1
@Component({
selector: 'level1',
template: `<div>I am level 1<level2></level2></div>`,
directives: [Level2]
})
export class Level1 {
@ViewChild(Level2) level2:Level2;
getName(){
return "my name is 'ONE'";
}
// You need to add additional function that would be called from level 1
calledFromLevel1() {
return this.level2.getName();
}
}
// Level 0
@Component({
selector: 'level0',
template: `<div>I am level 0<level1></level1></div>`,
directives: [Level1,Level2]
})
export class App {
@ViewChild(Level1) level1:Level1;
ngAfterViewInit() {
if(this.level1) {
var name1 = this.level1.getName();
var name2 = this.level1.calledFromLevel1();
}
console.log("name1",name1);
console.log("name2",name2);
}
}
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