Angular 8 - @ViewChild возвращает undefined для родительского компонента. (нет вложенного ngIf и вызывается в ngAfterViewInit) - PullRequest
1 голос
/ 19 апреля 2020

Надеюсь, что кто-то может просветить меня.

Проблема

Мне нужно получить ссылку на директиву, размещенную внутри внутреннего компонента. Я использую класс директивы нацеливания @ViewChild с {stati c: true}, так как ему не нужно ждать изменений состояния и использовать его позже на жизненном цикле, когда пользователь нажимает кнопку.

@ViewChild(DirectiveClass, {static:true}) childRef : DirectiveClass;

Ожидается, что

будет иметь ссылку на директиву в переменной экземпляра childRef при возникновении события.

Actual

childRef равно undefined

Я исследовал подобные проблемы и все, кажется, потому что ref был внутри * ngIf и должен быть {stati c: false}; или потому что ссылка была предназначена для использования до ее извлечения (до хука ngAfterViewInit). Это не тот случай, этот случай довольно прост, и все же не могу понять, что не так! : /

Воспроизведение

Ситуация

Итак, я получил два компонента и директиву. Давайте назовем их ParentComponent и SonComponent. Директива применяется в компоненте son, поэтому назовем его SonDirective.

В основном это структура.

<app-parent>
  <app-son> </app-son> //<- Directive inside
</app-parent>

Код

//parent.component.ts
@Component({
  selector: 'app-parent',
  template: `
    <div>
      <h2> parent </h2>
      <app-son></app-son>
    </div>
  `,
})
export class AppParentComponent implements AfterViewInit{

  @ViewChild(AppSonDirective,{static: true}) childRef : AppSonDirective;
  constructor() {}
  ngAfterViewInit() {
    console.log("childRef:",this.childRef)
  }
}
// son.component.ts
@Component({
  selector: 'app-son',
  template: `
    <div appSonDirective>
      <p> son <p>
    </div>
  `,
})
export class AppSonComponent {
  constructor() {}
}

//son.directive.ts
@Directive({
    selector: '[appSonDirective]'
})
export class AppSonDirective {
constructor(){}
}

Примечание: если я переместу дочерний элемент view в компонент son, он будет доступен. Кажется, проблема в родительском компоненте (?)

В любом случае ... здесь - это код воспроизведения (в нем есть несколько журналов, чтобы знать, что происходит)

Любые мысли будут полезны.

Заранее спасибо! :)

1 Ответ

0 голосов
/ 19 апреля 2020

Проблема в том, что @ViewChild работает только вокруг DOM компонента, но не имеет доступа к DOM его дочерних компонентов, что нарушит инкапсуляцию между компонентами. В этом случае appSonDirective объявляется в AppSonComponent DOM, но поскольку вы пытаетесь получить к нему доступ из AppParentComponent, возвращается undefined, поскольку AppParentComponent не может получить доступ к AppSonComponent DOM. Это могло бы работать, если бы у вас было что-то вроде этого:

<app-parent>
  <app-son appSonDirective></app-son> 
</app-parent>

Одним из решений является предоставление директивы как свойства вашего дочернего компонента. Что-то вроде:

@Component({
  selector: 'app-son',
  template: `
    <div appSonDirective>
      <p> son <p>
    </div>
  `,
})
export class AppSonComponent {
  @ViewChild(AppSonDirective,{static: true}) childRef : AppSonDirective;
  constructor() {}
}

, а затем в AppParentComponent

@Component({
  selector: 'app-parent',
  template: `
    <div>
      <h2> parent </h2>
      <app-son></app-son>
    </div>
  `,
})
export class AppParentComponent implements AfterViewInit{

  @ViewChild(AppSonComponent,{static: true}) son : AppSonComponent;
  constructor() {}
  ngAfterViewInit() {
    console.log("childRef:",this.son.childRef)
  }

}

...