{"id":13424218,"url":"https://github.com/Tinkoff/ng-event-plugins","last_synced_at":"2025-03-15T18:34:16.527Z","repository":{"id":38461625,"uuid":"238479214","full_name":"Tinkoff/ng-event-plugins","owner":"Tinkoff","description":"This is an Angular library for optimizing performance sensitive events and declarative preventDefault, stopPropagation and capture phase listeners.","archived":true,"fork":false,"pushed_at":"2023-05-26T03:34:56.000Z","size":2096,"stargazers_count":232,"open_issues_count":5,"forks_count":12,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-04-10T07:09:37.327Z","etag":null,"topics":["angular","angular-library","capture","events","optimization","preventdefault","stoppropagation","trigger-change-detection"],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/github/TinkoffCreditSystems/ng-event-plugins/tree/master/projects/demo","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tinkoff.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null}},"created_at":"2020-02-05T15:11:21.000Z","updated_at":"2024-02-13T07:29:24.000Z","dependencies_parsed_at":"2023-07-25T05:33:49.080Z","dependency_job_id":null,"html_url":"https://github.com/Tinkoff/ng-event-plugins","commit_stats":null,"previous_names":["tinkoffcreditsystems/ng-event-plugins","tinkoffcreditsystems/ng-event-filters"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tinkoff%2Fng-event-plugins","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tinkoff%2Fng-event-plugins/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tinkoff%2Fng-event-plugins/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tinkoff%2Fng-event-plugins/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tinkoff","download_url":"https://codeload.github.com/Tinkoff/ng-event-plugins/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243775787,"owners_count":20346261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular-library","capture","events","optimization","preventdefault","stoppropagation","trigger-change-detection"],"created_at":"2024-07-31T00:00:50.302Z","updated_at":"2025-03-15T18:34:11.490Z","avatar_url":"https://github.com/Tinkoff.png","language":"TypeScript","readme":"# Angular Event Plugins\n\n[![npm version](https://img.shields.io/npm/v/@tinkoff/ng-event-plugins.svg)](https://npmjs.com/package/@tinkoff/ng-event-plugins)\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/@tinkoff/ng-event-plugins)](https://bundlephobia.com/result?p=@tinkoff/ng-event-plugins)\n[![Coverage Status](https://coveralls.io/repos/github/TinkoffCreditSystems/ng-event-plugins/badge.svg?branch=master)](https://coveralls.io/github/TinkoffCreditSystems/ng-event-plugins?branch=master)\n[![angular-open-source-starter](https://img.shields.io/badge/made%20with-angular--open--source--starter-d81676?logo=angular)](https://github.com/TinkoffCreditSystems/angular-open-source-starter)\n[![telegram chat](https://img.shields.io/badge/support-Contact%20us-blue)](https://t.me/taiga_ui)\n\n**@tinkoff/ng-event-plugins** is a tiny (1KB gzip) library for optimizing change detection cycles for performance\nsensitive events (such as _touchmove_, _scroll_, _drag_ etc.) and declarative _preventDefault()_ and\n_stopPropagation()_.\n\n## How to use\n\n1. Add `EventPluginsModule` to your app module:\n\n   ```typescript\n   import {NgModule} from '@angular/core';\n   import {BrowserModule} from '@angular/platform-browser';\n   import {EventPluginsModule} from '@tinkoff/ng-event-plugins'; // \u003c-- THIS\n\n   @NgModule({\n     bootstrap: [\n       /*...*/\n     ],\n     imports: [\n       /*...*/\n       BrowserModule,\n       EventPluginsModule, // \u003c-- GOES HERE\n     ],\n     declarations: [\n       /*...*/\n     ],\n   })\n   export class AppModule {}\n   ```\n\n\u003e `BrowserModule` or `BrowserAnimationsModule` must go first. You will see a warning if you mess the order.\n\n2. Use new modifiers for events in templates and in `@HostListener`:\n\n   - `.stop` to call stopPropagation() on event\n   - `.prevent` to call preventDefault() on event\n   - `.self` to skip bubbled events\n   - `.silent` to call event handler outside Angular's `NgZone`\n   - `.capture` to listen to events in\n     [capture phase](https://developer.mozilla.org/en-US/docs/Web/API/Event/eventPhase)\n   - `.passive` to add\n     [passive event listener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners)\n   - `.once` to remove event listener after first callback\n\n   For example:\n\n   ```html\n   \u003cdiv (mousedown.prevent)=\"onMouseDown()\"\u003eClicking on this DIV will not move focus\u003c/div\u003e\n   ```\n\n   ```html\n   \u003cdiv (click.stop)=\"onClick()\"\u003eClicks on this DIV will not bubble up\u003c/div\u003e\n   ```\n\n   ```html\n   \u003cdiv (mousemove.silent)=\"onMouseMove()\"\u003eCallbacks to mousemove will not trigger change detection\u003c/div\u003e\n   ```\n\n   ```html\n   \u003cdiv (click.capture.stop)=\"onClick()\"\u003e\n     \u003cdiv (click)=\"never()\"\u003eClicks will be stopped before reaching this DIV\u003c/div\u003e\n   \u003c/div\u003e\n   ```\n\n3. You can also re-enter `NgZone` and trigger change detection, using `@shouldCall` decorator that takes a predicate\n   function as argument:\n\n```html\n\u003cdiv (scroll.silent)=\"onScroll($event.currentTarget)\"\u003e\n  Scrolling this DIV will only trigger change detection and onScroll callback if it is scrolled to bottom\n\u003c/div\u003e\n```\n\n```typescript\nimport {shouldCall} from '@tinkoff/ng-event-plugins';\n\nexport function scrollFilter({\n scrollTop, scrollHeight, clientHeight\n}: HTMLElement): boolean {\n    return scrollTop === scrollHeight - clientHeight;\n}\n\n// ...\n\n@shouldCall(scrollFilter)\nonScroll(_element: HTMLElement): void {\n    this.someService.requestMoreData();\n}\n```\n\n\u003e All examples above work the same when used with `@HostListener` and `CustomEvent`\n\n### Important notes\n\n- Predicate is called with the same arguments as the decorated method and in the context of class instance (has access\n  to `this`)\n\n- Decorated method will be called and change detection triggered if predicate returns `true`.\n\n- Predicates must be exported named function for AOT, arrow functions will trigger build error.\n\n- `.silent` modifier will not work with built-in keyboard pseudo-events, such as `keydown.enter` or `keydown.arrowDown`\n  since Angular re-enters `NgZone` inside internal handlers.\n\n## Observable host bindings\n\nIn this library there's also a plugin that enables observable host bindings. Sounds weird to do host binding with event\nplugin, but the code is actually pretty simple. You can read more about it in\n[this article](https://indepth.dev/posts/1429/making-hostbinding-work-with-observables).\n\nTo use it you need to couple `@HostListener` and `@HostBinding` on the same `Observable` property with following syntax:\n\n```ts\n@HostBinding('$.disabled')\n@HostListener('$.disabled')\nreadonly disabled$ = asCallable(this.service.loading$)\n```\n\nThis supports all the native Angular syntax, such as `class.class-name` or `style.width.px`.\n\n**IMPORTANT NOTES:**\n\n- Until [this issue](https://github.com/angular/angular/issues/12045) is resolved you would have to use\n  `NO_ERRORS_SCHEMA` in your module in order to bind to arbitrary properties\n- `asCallable` is a utility function from this library that simply adds `Function` to the type so Angular thinks it\n  could be a host listener\n- To bind attributes you need to add `.attr` modifier in the end, not the beginning like in basic Angular binding. This\n  is due to Angular using regexp to match for `attr.` string in `@HostBinding` decorator:\n\n```ts\n@HostBinding('$.aria-label.attr')\n@HostListener('$.aria-label.attr')\nreadonly label$ = asCallable(this.translations.get$('label'));\n```\n\n## Demo\n\nYou can try this\n[interactive demo](https://codesandbox.io/s/github/TinkoffCreditSystems/ng-event-plugins/tree/master/projects/demo)\n\nYou can also read this [detailed article](https://indepth.dev/supercharge-event-management-in-your-angular-application/)\nexplaining how this library works\n\n## Maintained\n\n**@tinkoff/ng-event-plugins** is a part of [Taiga UI](https://github.com/Tinkoff/taiga-ui) libraries family which is backed and used by a\nlarge enterprise. This means you can rely on timely support and continuous development.\n\n## License\n\n🆓 Feel free to use our library in your commercial and private applications\n\nAll **@tinkoff/ng-event-plugins** packages are covered by [Apache 2.0](/LICENSE)\n\nRead more about this license [here](https://choosealicense.com/licenses/apache-2.0/)\n\n## Open-source\n\nDo you also want to open-source something, but hate the collateral work? Check out this\n[Angular Open-source Library Starter](https://github.com/TinkoffCreditSystems/angular-open-source-starter) we’ve created\nfor our projects. It got you covered on continuous integration, pre-commit checks, linting, versioning + changelog, code\ncoverage and all that jazz.\n","funding_links":[],"categories":["Инструменты"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTinkoff%2Fng-event-plugins","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTinkoff%2Fng-event-plugins","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTinkoff%2Fng-event-plugins/lists"}