Получить элемент-элемент ng-content из шаблона - PullRequest
1 голос
/ 29 апреля 2020

Я пытаюсь сделать поповер с angular. Который в настоящее время имеет два компонента и одну директиву.

Когда я нажимаю на свою кнопку, я получаю сообщение об ошибке:

ОШИБКА TypeError: Невозможно прочитать свойство 'openPopover' из неопределенного

Как я могу получить ссылку на родителя из директивы, а затем получить дочерний элемент от этого родителя?

Итак, путь щелчка будет выглядеть так: [open-popover] / <map-popover> / <map-popover-content>

app.component. html

<mat-popover>
  <mat-popover-content>
    <p>Hello World</p>
  </mat-popover-content>
  <button mat-flat-button open-popover color="primary">Add Debt</button>
</mat-popover>

popover.component.ts

@Component({
  selector: 'mat-popover',
  template: '<ng-content></ng-content>',
  styleUrls: ['./popover.component.scss']
})
export class MatPopoverComponent {

  @ViewChild(MatPopoverContentComponent)
  public content: MatPopoverContentComponent

  public open() {
    this.content.openPopover()
  }
}

content.component .ts

@Component({
  selector: 'mat-popover-content',
  template: `<ng-template #popoverContent>
    <ng-content></ng-content>
  </ng-template>`,
  styleUrls: ['./content.component.scss']
})
export class MatPopoverContentComponent {

  @ViewChild('popoverContent')
  public template: TemplateRef<any>

  public constructor(public dialog: MatDialog) { }

  openPopover(): void {
    this.dialog.open(this.template, {
      hasBackdrop: false
    })
  }
}

open.directive.ts

@Directive({
  selector: '[open-popover]'
})
export class OpenPopoverDirective {

  public constructor(@Host() private popover: MatPopoverComponent) { }

  @HostListener('click')
  public onClick() {
    this.popover.open()
  }
}

1 Ответ

3 голосов
/ 29 апреля 2020

Замените ContentChild декоратор на ViewChild здесь @ViewChild(MatPopoverContentComponent), и оно должно работать.

Объяснение

Вы должны различать guish Light DOM и Shadow DOM:

компонент

@Component({
  selector: 'mat-popover',
  template: `<ng-content></ng-content>`, <--- Shadow DOM
  styleUrls: ['./popover.component.scss']
})
export class MatPopoverComponent {}

потребитель

<mat-popover>
  <!-- Light DOM starts -->
  <mat-popover-content>
    <p>Hello World</p>
  </mat-popover-content>
  <button mat-flat-button open-popover color="primary">Add Debt</button>
  <!-- Light DOM ends-->
</mat-popover>

Так что в Angular мы запрашиваем элементы в Shadow DOM с использованием ViewChild / ren и элементов в Light DOM с использованием ContentChild / ren

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...