Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@ViewChild: access grand-child methods

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

like image 212
Manube Avatar asked Apr 15 '16 18:04

Manube


People also ask

What is the difference between ViewChild () and ContentChild ()?

ViewChild is used to select an element from component's template while ContentChild is used to select projected content.

What is difference between ViewChild and ViewChildren?

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.

How do I access a component using ViewChild?

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.


1 Answers

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);
  }
}
like image 125
Sudeep Mukherjee Avatar answered Oct 07 '22 00:10

Sudeep Mukherjee