@ViewChild: access grand-child methods
Asked Answered
Q

2

8

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

Quarles answered 15/4, 2016 at 18:22 Comment(0)
T
3

I don't think this is currently possible.

The ViewQueryMetadata API doc says the following:

Supports the same querying parameters as QueryMetadata, except descendants.

The QueryMetadata API doc has this descendants example:

Configure whether query looks for direct children or all descendants of the querying element, by using the descendants parameter. It is set to false by default.

... code here not shown ...

When querying for items, the first container will see only a and b by default, but with Query(TextDirective, {descendants: true}) it will see c too.

Transudate answered 15/4, 2016 at 19:29 Comment(4)
@Manube, I think you'll be disappointed. I believe Query is deprecated in favor of ViewChild and ViewChildren. And if Query is still around, I don't think it supports descendants. (I tried playing around with it a bit in a Plunker before I answered this question, and I couldn't get it to work.)Transudate
Right, then I will try and think differently. As I wish to implement an app where a parent should know all its selected, nested descendants, I guess I will just keep the data in services and inject them in the parentQuarles
@MarkRajcok the links are broken, can you update your answer please?Filbert
@Filbert I believe the Query feature is now totally deprecated; you won't find any docs on it. ViewChild and ContentChild have to be used, which don't have a descendants query ability, as the 2nd comment above mentions.Olly
D
7

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);
  }
}
Dorathydorca answered 5/10, 2017 at 15:17 Comment(0)
T
3

I don't think this is currently possible.

The ViewQueryMetadata API doc says the following:

Supports the same querying parameters as QueryMetadata, except descendants.

The QueryMetadata API doc has this descendants example:

Configure whether query looks for direct children or all descendants of the querying element, by using the descendants parameter. It is set to false by default.

... code here not shown ...

When querying for items, the first container will see only a and b by default, but with Query(TextDirective, {descendants: true}) it will see c too.

Transudate answered 15/4, 2016 at 19:29 Comment(4)
@Manube, I think you'll be disappointed. I believe Query is deprecated in favor of ViewChild and ViewChildren. And if Query is still around, I don't think it supports descendants. (I tried playing around with it a bit in a Plunker before I answered this question, and I couldn't get it to work.)Transudate
Right, then I will try and think differently. As I wish to implement an app where a parent should know all its selected, nested descendants, I guess I will just keep the data in services and inject them in the parentQuarles
@MarkRajcok the links are broken, can you update your answer please?Filbert
@Filbert I believe the Query feature is now totally deprecated; you won't find any docs on it. ViewChild and ContentChild have to be used, which don't have a descendants query ability, as the 2nd comment above mentions.Olly

© 2022 - 2024 — McMap. All rights reserved.