@ViewChild: доступ к дочерним методам

У меня есть три вложенных компонента, называемых level0, level1 и level2, определенных следующим образом:

@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);
  }
}

В консоли я ожидал увидеть:

name1 my name is 'ONE'
name2 my name is 'TWO'

Но вместо этого я вижу:

name1 my name is 'ONE'
name2 undefined

Что мне не хватает? Почему компонент Level0 не может получить доступ от Level2 до @ViewChild?

Есть ли способ получить доступ к методам Level2 в Level0?


Вот plnkr


person Manube    schedule 15.04.2016    source источник


Ответы (2)


Я не думаю, что это возможно в настоящее время.

В документе ViewQueryMetadata API говорится следующее:

Поддерживает те же параметры запроса, что и QueryMetadata, за исключением потомков.

В документе API QueryMetadata есть следующий пример потомков:

Настройте, ищет ли запрос прямых дочерних элементов или всех потомков запрашивающего элемента, используя параметр потомков. По умолчанию установлено значение false.

... код здесь не показан...

При запросе элементов первый контейнер по умолчанию увидит только a и b, но с Query(TextDirective, {descendants: true}) он также увидит c.

person Mark Rajcok    schedule 15.04.2016
comment
@ Манубе, я думаю, ты будешь разочарован. Я считаю, что Query устарел в пользу ViewChild и ViewChildren. И если Query все еще существует, я не думаю, что он поддерживает descendants. (Я пытался немного поиграть с ним в Plunker, прежде чем ответить на этот вопрос, и я не смог заставить его работать.) - person Mark Rajcok; 15.04.2016
comment
Хорошо, тогда я попытаюсь думать иначе. Поскольку я хочу реализовать приложение, в котором родитель должен знать всех своих выбранных вложенных потомков, я думаю, что просто буду хранить данные в службах и вводить их в родителя. - person Manube; 15.04.2016
comment
@MarkRajcok, ссылки не работают, не могли бы вы обновить свой ответ, пожалуйста? - person stackdave; 22.08.2016
comment
@stackdave Я считаю, что функция Query теперь полностью устарела; вы не найдете на нем никаких документов. Необходимо использовать ViewChild и ContentChild, которые не имеют возможности запроса потомков, как упоминается во втором комментарии выше. - person pbarranis; 31.08.2018

Это может быть достигнуто, если вы используете ViewChild на каждом уровне ваших вложенных компонентов, например так:

// 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);
  }
}
person Sudeep Mukherjee    schedule 05.10.2017