Skip to content

Commit

Permalink
fix(click-outside): remove memory leak (#319)
Browse files Browse the repository at this point in the history
* fix(click-outside): remove memory leak

* fix(click-outside): remove memory leak

---------

Co-authored-by: Krzysztof <[email protected]>
  • Loading branch information
kkachniarz220 and Krzysztof authored Apr 23, 2024
1 parent 5542a8c commit 49bff56
Showing 1 changed file with 18 additions and 15 deletions.
33 changes: 18 additions & 15 deletions libs/ngxtension/click-outside/src/click-outside.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,27 @@ import {
NgZone,
Output,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { createInjectionToken } from 'ngxtension/create-injection-token';
import { injectDestroy } from 'ngxtension/inject-destroy';
import { filter, fromEvent, Subject, takeUntil } from 'rxjs';
import { filter, fromEvent, Subject } from 'rxjs';

/*
* This function is used to detect clicks in the document.
* It is used by the clickOutside directive.
*/
const [injectDocumentClick] = createInjectionToken(() => {
const click$ = new Subject<Event>();
const [ngZone, document] = [inject(NgZone), inject(DOCUMENT)];
const [injectDocumentClick, provideDocumentClick] = createInjectionToken(
() => {
const click$ = new Subject<Event>();
const [ngZone, document] = [inject(NgZone), inject(DOCUMENT)];

ngZone.runOutsideAngular(() => {
fromEvent(document, 'click').subscribe(click$);
});
ngZone.runOutsideAngular(() => {
fromEvent(document, 'click').pipe(takeUntilDestroyed()).subscribe(click$);
});

return click$;
});
return click$.asObservable();
},
{ isRoot: false },
);

/*
* This directive is used to detect clicks outside the element.
Expand All @@ -34,14 +37,16 @@ const [injectDocumentClick] = createInjectionToken(() => {
* <div (clickOutside)="close()"></div>
*
*/
@Directive({ selector: '[clickOutside]', standalone: true })
@Directive({
selector: '[clickOutside]',
standalone: true,
providers: [provideDocumentClick()],
})
export class ClickOutside implements OnInit {
private ngZone = inject(NgZone);
private elementRef = inject(ElementRef);
private documentClick$ = injectDocumentClick();

private destroy$ = injectDestroy();

/*
* This event is emitted when a click occurs outside the element.
*/
Expand All @@ -50,13 +55,11 @@ export class ClickOutside implements OnInit {
ngOnInit() {
this.documentClick$
.pipe(
takeUntil(this.destroy$),
filter(
(event: Event) =>
!this.elementRef.nativeElement.contains(event.target),
),
)

.subscribe((event: Event) => {
this.ngZone.run(() => this.clickOutside.emit(event));
});
Expand Down

0 comments on commit 49bff56

Please sign in to comment.