Angular custom event bubbling

Custom events in Angular by default do not bubble up. It is because they are not really events, they are based on EventEmitter, which is┬ásimilar to pub/sub mechanism. You can read lengthy discussion about it on Angular’s Github. Unfortunately the examples provided by Angular team often mention $event as named parameter in the event listener, which only adds to the confusion. There are valid use cases when you really need the custom events to bubble up.

Luckily, you can still create DOM-native custom events, and they will bubble up as expected.

import { Component, OnInit, Input, ElementRef, Renderer } from '@angular/core';

@Component({
  selector: 'app-bubble',
  templateUrl: './bubble.component.html',
  styleUrls: ['./bubble.component.scss']
})
export class BubbleComponent implements OnInit {

  /**
   * Optional.
   * Defaults to 'myCustomEvent'
   */
  @Input()
  customEventName: string;

  private _defaultEventName: string = 'myCustomEvent';

  /**
   * Invokes DOM-native custom event, which bubbles up.
   * That solves the issue with EventEmmiter-based events, which are not really events and do not bubble up.
   */
  emitEvent() {
    const eventName = this.customEventName || this._defaultEventName;

    this.renderer.invokeElementMethod(
      this.elRef.nativeElement,
      'dispatchEvent',
      [new CustomEvent(eventName, {bubbles: true})]
    );
  }

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

  ngOnInit() {
  }

}

And the html template

<button (click)="emitEvent()">Emit custom event which bubbles up</button>

Then somewhere up the DOM tree, you listen for the event like this

<app-my-listener (myCustomEvent)="doSomething($event)"></app-my-listener>

More reading:

https://www.radzen.com/blog/angular-event-bubbling/