Skip to content

Instantly share code, notes, and snippets.

@theer1k
Last active June 27, 2023 11:40
Show Gist options
  • Save theer1k/3df508fcc57bda7c140838de1f2ef338 to your computer and use it in GitHub Desktop.
Save theer1k/3df508fcc57bda7c140838de1f2ef338 to your computer and use it in GitHub Desktop.
IntersectionObserverDirective (Angular)
import {
Directive,
ElementRef,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
} from '@angular/core';
import { Observable, Subscription, debounceTime } from 'rxjs';
@Directive({
selector: '[appObserveElement]',
exportAs: 'intersection',
standalone: true,
})
export class IntersectionObserverDirective implements OnInit, OnDestroy {
@Input() root: HTMLElement | null = null;
@Input() rootMargin = '100px 0px 0px 0px';
@Input() threshold = 0;
@Input() debounceTime = 50;
@Input() isContinuous = false;
@Output() isIntersecting = new EventEmitter<boolean>();
_isIntersecting = false;
subscription!: Subscription;
constructor(private element: ElementRef) {}
ngOnInit() {
this.subscription = this.createAndObserve();
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
createAndObserve() {
const options: IntersectionObserverInit = {
root: this.root,
rootMargin: this.rootMargin,
threshold: this.threshold,
};
return new Observable<boolean>((subscriber) => {
const intersectionObserver = new IntersectionObserver((entries) => {
const { isIntersecting } = entries[0];
subscriber.next(isIntersecting);
isIntersecting &&
!this.isContinuous &&
intersectionObserver.disconnect();
}, options);
intersectionObserver.observe(this.element.nativeElement);
return {
unsubscribe() {
intersectionObserver.disconnect();
},
};
})
.pipe(debounceTime(this.debounceTime))
.subscribe((status) => {
this.isIntersecting.emit(status);
this._isIntersecting = status;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment