Search code examples
angularevents

Capturing events emitted from components inside <ng-content>?


I have a custom modal component which uses <ng-content> to transclude content:

@Component({
  selector: 'modal-container',
  template: `
    <div [class]="css">
      <div [attr.id]="id" class="reveal" (open)="openModal()">
        <ng-content></ng-content>
      </div>
    </div>
  `
})
export class ModalContainerComponent {
    . . .
}

In the contents of <ng-content> I have a component which emits the open event:

@Component({
  selector: 'login-modal',
  template: `
    <modal-container [id]="'login-modal'">
      <section>...</section>
    </modal-container>
  `,
})
export class LoginModalComponent implements OnInit {

    @Output()
    open = new EventEmitter();

    ngOnInit(): void {
        // Here I am checking an ngrx store with code that is not included
        if (state.openLoginModal) {
          this.open.emit();
        }
    }

}

however, the ModalContainerComponent never receives the event.

Examples such as:

are coming up short. What am I doing wrong?


Update:

Since @Output events don't bubble, I decided to go with a custom directive to emit the event:

import { Directive, ElementRef, Renderer } from '@angular/core';


@Directive({
  selector: '[open-modal]',
  host: { '(click)': 'openModal()' }
})
export class OpenModalDirective {

  constructor(
    private elementRef: ElementRef,
    private renderer: Renderer
  ) {}

  openModal(): void {
    this.renderer.invokeElementMethod(this.elementRef.nativeElement,
      'dispatchEvent',
      [new CustomEvent('open-modal-container', { bubbles: true })]);
  }

}

using: in Angular2 how to know when ANY form input field lost focus as an example.

However, I still can't pick up the custom event in ModalContainerComponent:

@HostListener('open-modal-container')
openModalContainer(): void {
  console.log('openModal() was invoked');
}

I can log the click event, so that's happening, but the host listener is failing. Thoughts?


Update 2

I'm abandoning this approach in favor of a shared service, but I'm running into an issue with .next() not providing a value to the subscriber: Subscriber doesn't receive value from .next()


Solution

  • I ended up abandoning the event-driven approach and went with a shared service class instead.