Skip to content

Instantly share code, notes, and snippets.

@johannesMatevosyan
Last active May 6, 2026 09:26
Show Gist options
  • Select an option

  • Save johannesMatevosyan/92f5cc40df70d71db8f2a6d27d90c63c to your computer and use it in GitHub Desktop.

Select an option

Save johannesMatevosyan/92f5cc40df70d71db8f2a6d27d90c63c to your computer and use it in GitHub Desktop.
Reusable Angular Click Outside Directive (Standalone, Memory-safe)
import {
Directive,
ElementRef,
EventEmitter,
OnDestroy,
OnInit,
Output,
Renderer2,
inject,
} from '@angular/core';
@Directive({
selector: '[appClickOutside]',
standalone: true,
})
export class ClickOutsideDirective implements OnInit, OnDestroy {
private readonly elementRef = inject(ElementRef<HTMLElement>);
private readonly renderer = inject(Renderer2);
@Output() appClickOutside = new EventEmitter<void>();
private removeListener: (() => void) | null = null;
ngOnInit(): void {
this.removeListener = this.renderer.listen(
'document',
'click',
(event: Event) => this.handleClick(event)
);
}
private handleClick(event: Event): void {
const target = event.target as Node | null;
if (!target) {
return;
}
if (!this.elementRef.nativeElement.contains(target)) {
this.appClickOutside.emit();
}
}
ngOnDestroy(): void {
this.removeListener?.();
}
}

Usage

<div appClickOutside (appClickOutside)="closeDropdown()">
  <!-- dropdown content -->
</div>

Example: dropdown

<div class="dropdown" appClickOutside (appClickOutside)="isOpen = false">
  <button (click)="isOpen = !isOpen">Toggle</button>

  <div *ngIf="isOpen" class="menu">
    Dropdown content
  </div>
</div>

Use cases

  • Dropdown menus
  • Notification panels
  • Modals
  • Context menus
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment