|
| 1 | +--- |
| 2 | +title: onEvent |
| 3 | +description: A small utility to add DOM/EventTarget listeners with automatic cleanup via DestroyRef. |
| 4 | +entryPoint: ngxtension/on-event |
| 5 | +badge: stable |
| 6 | +contributors: ['endlacer'] |
| 7 | +--- |
| 8 | + |
| 9 | +A small utility for listening to events on any `EventTarget` with automatic cleanup when the current Angular lifecycle |
| 10 | +scope is destroyed (via `DestroyRef.onDestroy`). |
| 11 | +It uses an `AbortController` and passes its `signal` to `addEventListener`, so aborting removes the listener without |
| 12 | +needing `removeEventListener`. |
| 13 | + |
| 14 | +## Usage |
| 15 | + |
| 16 | +### Basic Usage with Auto-Cleanup |
| 17 | + |
| 18 | +Listen to an event and auto-cleanup on destroy (when called inside an injection context): |
| 19 | + |
| 20 | +```ts |
| 21 | +import { onEvent } from 'ngxtension/on-event'; |
| 22 | + |
| 23 | +onEvent(window, 'resize', (event) => { |
| 24 | + console.log('Window resized', event); |
| 25 | +}); |
| 26 | +``` |
| 27 | + |
| 28 | +### Manual Control (Abort inside callback) |
| 29 | + |
| 30 | +Stop listening manually (e.g., after the first "meaningful" event): |
| 31 | + |
| 32 | +```ts |
| 33 | +onEvent(document, 'scroll', (event, abort) => { |
| 34 | + if (window.scrollY > 500) { |
| 35 | + console.log('User scrolled past 500px'); |
| 36 | + abort(); // removes the listener immediately |
| 37 | + } |
| 38 | +}); |
| 39 | +``` |
| 40 | + |
| 41 | +### Control via Return Value |
| 42 | + |
| 43 | +You can control the listener from outside the callback using the returned object. This is useful for UI feedback based |
| 44 | +on the listener's state. |
| 45 | + |
| 46 | +```ts |
| 47 | +const { destroy, active } = onEvent(window, 'mousemove', (e) => { |
| 48 | + // heavy logic |
| 49 | +}); |
| 50 | + |
| 51 | +// Check if we are currently listening (returns Signal<boolean>) |
| 52 | +console.log(active()); // true |
| 53 | + |
| 54 | +// Stop listening from outside |
| 55 | +destroy(); |
| 56 | + |
| 57 | +console.log(active()); // false |
| 58 | +``` |
| 59 | + |
| 60 | +## Options |
| 61 | + |
| 62 | +```ts |
| 63 | +type OnEventOptions = { |
| 64 | + once?: boolean; |
| 65 | + capture?: boolean; |
| 66 | + passive?: boolean; |
| 67 | +}; |
| 68 | +``` |
| 69 | + |
| 70 | +- `once`: Uses the native `addEventListener({ once: true })` behavior (listener runs once and is then removed). |
| 71 | +- `capture`: A boolean indicating that events of this type will be dispatched to the registered listener before being |
| 72 | + dispatched to any EventTarget beneath it in the DOM tree. |
| 73 | +- `passive`: A boolean which, if true, indicates that the function specified by listener will never call |
| 74 | + `preventDefault()`. |
| 75 | +- `destroyRef`: Provide a `DestroyRef` explicitly (useful outside injection context, or when you want a specific |
| 76 | + lifecycle scope). |
| 77 | +- `injector`: Provide an `Injector` explicitly so the utility can resolve `DestroyRef` from it when you're not in a |
| 78 | + direct injection context. |
| 79 | + |
| 80 | +## Injection notes |
| 81 | + |
| 82 | +If you call `onEvent()` somewhere without an active injection context (for example, inside a plain function that isn't |
| 83 | +run via Angular DI), pass either: |
| 84 | + |
| 85 | +- `options.destroyRef`, or |
| 86 | +- `options.injector`. |
| 87 | + |
| 88 | +If no `DestroyRef` can be determined, a warning will be logged in DevMode, and the listener will **not** be |
| 89 | +automatically cleaned up (you must call `destroy` manually). |
| 90 | + |
| 91 | +## API |
| 92 | + |
| 93 | +```ts |
| 94 | +export type OnEventResult = { |
| 95 | + destroy: () => void; |
| 96 | + active: Signal<boolean>; |
| 97 | +} |
| 98 | + |
| 99 | +onEvent(target: EventTarget, eventKey: string, listener: (event: Event, abort: () => void) => void, options?: OnEventOptions): OnEventResult; |
| 100 | +``` |
| 101 | + |
| 102 | +### Arguments |
| 103 | + |
| 104 | +- `target`: The DOM element or EventTarget (e.g., `window`, `document`, `ElementRef.nativeElement`). |
| 105 | +- `eventKey`: The name of the event (e.g., `'click'`, `'scroll'`). |
| 106 | +- `listener`: The callback function. Receives: |
| 107 | + - `event`: The dispatched event (typed via `GlobalEventHandlersEventMap` when possible). |
| 108 | + - `abort()`: Call to stop listening immediately. |
| 109 | +- `options`: Configuration object for event behavior and dependency injection. |
| 110 | + |
| 111 | +### Return Value |
| 112 | + |
| 113 | +Returns an `OnEventResult` object: |
| 114 | + |
| 115 | +- `destroy`: A function to remove the event listener manually. |
| 116 | +- `active`: A generic Angular `Signal<boolean>` indicating whether the listener is currently attached. |
0 commit comments