@tinkoff/ng-event-plugins is a tiny (1KB gzip) library for optimizing change detection cycles for performance sensitive events (such as touchmove, scroll, drag etc.) and declarative preventDefault() and stopPropagation().
- 
Add
EventPluginsModuleto your app module:import {NgModule} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {EventPluginsModule} from '@tinkoff/ng-event-plugins'; // <-- THIS @NgModule({ bootstrap: [ /*...*/ ], imports: [ /*...*/ BrowserModule, EventPluginsModule, // <-- GOES HERE ], declarations: [ /*...*/ ], }) export class AppModule {}
 
BrowserModuleorBrowserAnimationsModulemust go first. You will see a warning if you mess the order.
- 
Use new modifiers for events in templates and in
@HostListener:.stopto call stopPropagation() on event.preventto call preventDefault() on event.selfto skip bubbled events.silentto call event handler outside Angular'sNgZone.captureto listen to events in capture phase.passiveto add passive event listener.onceto remove event listener after first callback
For example:
<div (mousedown.prevent)="onMouseDown()">Clicking on this DIV will not move focus</div>
<div (click.stop)="onClick()">Clicks on this DIV will not bubble up</div>
<div (mousemove.silent)="onMouseMove()">Callbacks to mousemove will not trigger change detection</div>
<div (click.capture.stop)="onClick()"> <div (click)="never()">Clicks will be stopped before reaching this DIV</div> </div>
 - 
You can also re-enter
NgZoneand trigger change detection, using@shouldCalldecorator that takes a predicate function as argument: 
<div (scroll.silent)="onScroll($event.currentTarget)">
  Scrolling this DIV will only trigger change detection and onScroll callback if it is scrolled to bottom
</div>import {shouldCall} from '@tinkoff/ng-event-plugins';
export function scrollFilter({
 scrollTop, scrollHeight, clientHeight
}: HTMLElement): boolean {
    return scrollTop === scrollHeight - clientHeight;
}
// ...
@shouldCall(scrollFilter)
onScroll(_element: HTMLElement): void {
    this.someService.requestMoreData();
}All examples above work the same when used with
@HostListenerandCustomEvent
- 
Predicate is called with the same arguments as the decorated method and in the context of class instance (has access to
this) - 
Decorated method will be called and change detection triggered if predicate returns
true. - 
Predicates must be exported named function for AOT, arrow functions will trigger build error.
 - 
.silentmodifier will not work with built-in keyboard pseudo-events, such askeydown.enterorkeydown.arrowDownsince Angular re-entersNgZoneinside internal handlers. 
In this library there's also a plugin that enables observable host bindings. Sounds weird to do host binding with event plugin, but the code is actually pretty simple. You can read more about it in this article.
To use it you need to couple @HostListener and @HostBinding on the same Observable property with following syntax:
@HostBinding('$.disabled')
@HostListener('$.disabled')
readonly disabled$ = asCallable(this.service.loading$)This supports all the native Angular syntax, such as class.class-name or style.width.px.
IMPORTANT NOTES:
- Until this issue is resolved you would have to use
NO_ERRORS_SCHEMAin your module in order to bind to arbitrary properties asCallableis a utility function from this library that simply addsFunctionto the type so Angular thinks it could be a host listener- To bind attributes you need to add 
.attrmodifier in the end, not the beginning like in basic Angular binding. This is due to Angular using regexp to match forattr.string in@HostBindingdecorator: 
@HostBinding('$.aria-label.attr')
@HostListener('$.aria-label.attr')
readonly label$ = asCallable(this.translations.get$('label'));You can try this interactive demo
You can also read this detailed article explaining how this library works
@tinkoff/ng-event-plugins is a part of Taiga UI libraries family which is backed and used by a large enterprise. This means you can rely on timely support and continuous development.
🆓 Feel free to use our library in your commercial and private applications
All @tinkoff/ng-event-plugins packages are covered by Apache 2.0
Read more about this license here
Do you also want to open-source something, but hate the collateral work? Check out this Angular Open-source Library Starter we’ve created for our projects. It got you covered on continuous integration, pre-commit checks, linting, versioning + changelog, code coverage and all that jazz.