Захват события на нг-контенте в Angular 2

Я прохожу этот урок, чтобы понять угловые 2 ng-content, Я хочу захватить событие, которое срабатывает на ng-content, У меня есть следующий компонент:

@Component({
    moduleId: module.id,
    selector: 'card',
    template: `
    <ng-content (click)="onClick($event)"></ng-content>
    `
})
export class CardComponent {

    onClick(){
        console.log('clicked');
    }
}

Здесь, как вы можете видеть, я настраиваю слушателя на click событие. Но по ряду причин это не срабатывает. Похоже на весь ng-content тег заменен. Итак, чтобы запечатлеть событие, в настоящее время я делаю это:

template: `
    <div (click)="onClick($event)">
      <ng-content></ng-content>
    </div>
    `

Есть ли лучший способ сделать это? потому что я не хочу обернуть ng-content в div чтобы избежать проблем с укладкой. Благодарю. Plnkr

2 ответа

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

import { Component, HostListener } from '@angular/core';

@Component({
  selector: 'card',
  template: `<ng-content></ng-content>`
})
export class ButtonComponent {

  @HostListener('click', ['$event.target'])
  onClick(target) {
    console.log('Clicked on: ', target);
  }

}

Вы можете использовать @ContentChild для захвата событий проецируемого компонента.

Ребенок:

@Component({
moduleId: module.id,
selector: 'card-child',
template: `
<div>Card Child component</div>
`
})
export class CardChildComponent {
     @Output customEvent:EventEmitter = new EventEmitter()
}

Родитель:

@Component({
moduleId: module.id,
selector: 'card',
template: `
<ng-content></ng-content>
`
})
export class CardComponent {
    @ContentChild(CardChildComponent) childComp: CardChildComponent;

    ngAfterContentInit() {
        this.childComp.addEventListener("click", ()=>{console.log("clicked"});
        //Below is handling of custom event
        this.childComp.customEvent.subscribe(()=>{console.log("clicked"});
    }
}

Ниже показано, как будет вводиться компонент.

<card>
<card-child></card-child>
</card>

<ng-content> это просто заполнитель для включения содержимого в теги компонента. Angular заменяет его.

Единственная возможность избежать использования DIV решение, было бы создать свою собственную версию ng-content,

По сути, вы просто создаете пустой компонент и в шаблоне <ng-content> тег. Если вы называете этот компонент AppContentComponent (приложение-контент), то вы можете, в ваших компонентах,

<app-content (click)="onClick()">
   <ng-content></ng-content>
</app-content>

Конечно, это немного запутанно, и вы в конечном итоге оборачиваете свой включенный контент в другой тег (не <div>, но <app-content>), хотя, конечно, изначально вы не возражали против <ng-content> так что я думаю, что это может сработать для вас.

Другие вопросы по тегам