Last update on Saturday, January 12th 2019

Global Events and Event Delegation in Angular 2

In Angular 2, we are used to listening for events on the Component's DOM elements, however how do we listen to events outside of this range? Two ways to do this:

  1. Creating a Host Listener
  2. Using the Component's host property

The Host Listener Way

Angular 2 provides a HostListener Decorator in order to match an event triggered on a target with a function declared on the next line.
Just like this:

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

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  @HostListener("document:click", ["$event"])
  onDocumentClicked(ev) {
    console.log("clicked", ev);
  }
}

The syntax is as follow: 'target:event', [args].
When clicking on the document, we will be able to use the event triggered, you can also pass other arguments like $event.target for example.
However the target must be global, if you prefer, you can replace document by window.

The Host Way

Angular 2 Components provide a host property in order to match a function with an event triggered on a target.

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

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
  host: {
    "(document:click)": "onDocumentClicked($event)"
  }
})
export class AppComponent {
  onDocumentClicked(ev) {
    console.log("clicked", ev);
  }
}

The syntax is as follow: ('target:event)': 'function(args)'.
Same mechanism as the HostListener, only global and configuration friendly.

Event Delegation

Now that we have more experience under our belt, we can tackle one very important JavaScript concept: Event Delegation.

I discovered this concept thanks to the Great David Walsh, head there for a quick 5-minutes read.

5 minutes later

So how do we do this in Angular 2?
Let's start by using a similar template:

<ul #ulEl id="parent-list">
  <li id="post-1">Item 1</li>
  <li id="post-2">Item 2</li>
  <li id="post-3">Item 3</li>
  <li id="post-4">Item 4</li>
  <li id="post-5">Item 5</li>
  <li id="post-6">Item 6</li>
</ul>

Notice the #ulEl?
It's a reference that we will use in order to attach the listener in our Component here:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor (private renderer: Renderer){ }
  @ViewChild('ulEl') ulEl: ElementRef;

  ngOnInit() {
    this.tmpListener = this.renderer.listen(this.ulEl.nativeElement, 'click', this.logElement);
  }

  // Shorthand to get event.target
  logElement({target}) {
      if(target && target.nodeName == "LI") {
      console.log('Target id: ', target.id);
      // Add Business Logic here
    }
  }

  ngOnDestroy() {
    this.tmpListener();
  }
}

We get our ul Element and stock it as an ElementRef.
When we init our Component, we use the Renderer (for cross-platform compatibility) in order to attach an EventListener.
If the <ul> or a <li> tag is clicked, we trigger the logElement function.

This function will acquire the target from the event, if this target is a <li> tag we log the id property.

Conclusion

As usual many ways to do the work.
I prefer to go with the host property of a Component, this solution clearly lists every listener - target - function matching.
Event Delegation is an interesting trick that can help you for specific cases, it's being discussed a lot in the community, some times as a savior (see the comments here) and on other cases just as a little plus (there).

Action Range and spooky Sounds in an AR Ionic app with Wikitude

Learn how to use Wikitude's Action...

Adding Redux to an Ionic Application

Learn how to mix together your...

Adding Sounds using HTML5 and Native Audio in Ionic

Learn how to implement...

Stay up to date


Join over 4000 other developers who already receive my tutorials and their source code out of the oven with other free JavaScript courses and an Angular cheatsheet!