Skip to content

Instantly share code, notes, and snippets.

@navix
Last active December 25, 2018 10:11
Show Gist options
  • Select an option

  • Save navix/d23bfa26615b18c3fe46b649db7ceb59 to your computer and use it in GitHub Desktop.

Select an option

Save navix/d23bfa26615b18c3fe46b649db7ceb59 to your computer and use it in GitHub Desktop.
Custom EventManagerPlugin for Angular 7

Custom EventManagerPlugin for Angular 7

In Angular we can extend the events binding syntax. Let's add posibility to log an event before firing a handler.

Create custom event plugin:

import { Injectable } from '@angular/core';
import { EventManager, ɵgetDOM as getDOM } from '@angular/platform-browser';

/**
 * A plug-in that logs event to the console before firing.
 *
 * ```html
 * <button (click.log)="handler()">Handle&log</button>
 * ```
 *
 * **Warning**: it can not be stacked with another plugin-based handlers. Like key events (e.g. `(keydown.alt)`) or hammer gestures
 * (e.g. `(swipe)`). `EventManager` uses only one suitable plugin.
 */
@Injectable()
export class EventsLogPlugin {
  /**
   * The manager will get injected by the EventPluginManager at runtime.
   */
  manager!: EventManager;

  /**
   * Check that event has `.log` suffix.
   */
  supports(eventName: string): boolean {
    return !!this.parseName(eventName);
  }

  /**
   * Registers a handler for an event.
   */
  addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
    const outsideHandler = (event: any) => {
      // Log event before calling handler.
      console.log('Event log', {element, eventName, event});
      // Run handler in the zone.
      this.manager.getZone().runGuarded(() => handler(event));
    };
    // Add event listener and return listener remover.
    return this.manager.getZone().runOutsideAngular(() => {
      return getDOM().onAndCancel(element, this.parseName(eventName), outsideHandler);
    });
  }

  private parseName(eventName: string) {
    const parts: string[] = eventName.toLowerCase().split('.');
    const domEventName = parts.shift();
    if (parts.indexOf('log') !== -1) {
      return domEventName;
    }
  }
}

Register the plugin in the root module:

...
import { BrowserModule, EVENT_MANAGER_PLUGINS } from '@angular/platform-browser';
import { EventsLogPlugin } from './events-log-plugin';

@NgModule({
  ...
  providers: [
    {
      provide: EVENT_MANAGER_PLUGINS,
      useClass: EventsLogPlugin,
      multi: true,
    },
  ],
})
export class AppModule {
}

Use the new feature:

<button (click.log)="handler($event)">Click me and check the console</button>

Inspired by: https://www.bennadel.com/blog/3551-creating-a-dom-events-plug-in-that-configures-host-bindings-outside-of-the-angular-zone-in-angular-7-1-4.htm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment