Skip to content

Commit

Permalink
feat(global): add new plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
waterplea authored and splincode committed Apr 10, 2024
1 parent 2a85a47 commit cadf832
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ onScroll(_element: HTMLElement): void {
}
```
4. Angular global events only support `body`, `window` and `document`. You can listen to events on any global object
with these plugins by replacing `:` with `>` symbol, for example:
```ts
@HostListener('visualViewport>resize', ['$event.target'])
onPunchZoom({ scale }: VisualViewport) {
console.log(scale)
}
```
> All examples above work the same when used with `@HostListener` and `CustomEvent`
### Important notes
Expand Down
2 changes: 2 additions & 0 deletions projects/ng-event-plugins/src/constants/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {Provider} from '@angular/core';
import {EVENT_MANAGER_PLUGINS} from '@angular/platform-browser';

import {BindEventPlugin} from '../plugins/bind.plugin';
import {GlobalEventPlugin} from '../plugins/global.plugin';
import {OptionsEventPlugin} from '../plugins/options.plugin';
import {PreventEventPlugin} from '../plugins/prevent.plugin';
import {SelfEventPlugin} from '../plugins/self.plugin';
Expand All @@ -11,6 +12,7 @@ import {StopEventPlugin} from '../plugins/stop.plugin';
const PLUGINS = [
SilentEventPlugin,
BindEventPlugin,
GlobalEventPlugin,
OptionsEventPlugin,
PreventEventPlugin,
SelfEventPlugin,
Expand Down
32 changes: 32 additions & 0 deletions projects/ng-event-plugins/src/plugins/global.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {DOCUMENT} from '@angular/common';
import {inject, Injectable, InjectionToken} from '@angular/core';

import {AbstractEventPlugin} from './abstract.plugin';

export const GLOBAL_HANDLER = new InjectionToken<(name: string) => EventTarget>(
'[GLOBAL_HANDLER]: Global event target handler',
{
factory: () => {
const document = inject(DOCUMENT);

return name =>
name === 'body'
? document.body
: (document.defaultView as any)[name] || document.defaultView;
},
},
);

@Injectable()
export class GlobalEventPlugin extends AbstractEventPlugin {
private readonly handler: Function = inject(GLOBAL_HANDLER);
protected readonly modifier = '>';

public addEventListener(_: HTMLElement, event: string, handler: Function): Function {
return this.manager.addEventListener(
this.handler(event.split('>')[0]),
event.split('>')[1],
handler,
);
}
}
1 change: 1 addition & 0 deletions projects/ng-event-plugins/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './constants/plugins';
export * from './decorators/should-call';
export * from './module';
export * from './plugins/bind.plugin';
export * from './plugins/global.plugin';
export * from './plugins/options.plugin';
export * from './plugins/prevent.plugin';
export * from './plugins/silent.plugin';
Expand Down
15 changes: 15 additions & 0 deletions projects/ng-event-plugins/src/test/test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ describe('EventManagers', () => {
public readonly test = asCallable(new BehaviorSubject<number | null>(1));

public flag = false;
public custom = false;
public onStoppedClick = jasmine.createSpy('onStoppedClick');
public onPreventedClick = jasmine.createSpy('onPreventedClick');
public onWrapper = jasmine.createSpy('onWrapper');
Expand All @@ -87,6 +88,11 @@ describe('EventManagers', () => {
public onFilteredClicks(_bubbles: boolean): void {
this.flag = true;
}

@HostListener('document>custom')
public onCustom(): void {
this.custom = true;
}
}

let fixture: ComponentFixture<TestComponent>;
Expand All @@ -108,6 +114,15 @@ describe('EventManagers', () => {
testComponent.onBubbled.calls.reset();
});

it('Global events work', () => {
const event = new CustomEvent('custom');

document.dispatchEvent(event);
fixture.detectChanges();

void expect(testComponent.custom).toBe(true);
});

it('Clicks are stopped', () => {
const event = new Event('click', {bubbles: true});
const element = fixture.debugElement.query(
Expand Down

0 comments on commit cadf832

Please sign in to comment.