1
- import { Injectable , OnDestroy } from '@angular/core' ;
1
+ import { isPlatformServer } from '@angular/common' ;
2
+ import { ElementRef , inject , Injectable , OnDestroy , PLATFORM_ID } from '@angular/core' ;
2
3
import { BehaviorSubject } from 'rxjs' ;
3
4
4
5
export interface IIntersectionObserverInit {
@@ -7,40 +8,58 @@ export interface IIntersectionObserverInit {
7
8
threshold ?: number | number [ ] ;
8
9
}
9
10
10
- @Injectable ( )
11
+ @Injectable (
12
+ { providedIn : 'root' }
13
+ )
11
14
export class IntersectionService implements OnDestroy {
12
15
13
- constructor ( ) { }
16
+ platformId = inject ( PLATFORM_ID ) ;
14
17
15
- private intersecting = new BehaviorSubject < boolean > ( false ) ;
16
- intersecting$ = this . intersecting . asObservable ( ) ;
18
+ readonly # intersecting = new BehaviorSubject < boolean > ( false ) ;
19
+ readonly intersecting$ = this . # intersecting. asObservable ( ) ;
17
20
18
21
private intersectionObserver ! : IntersectionObserver ;
19
- private hostElement ! : { nativeElement : Element ; } ;
22
+ private hostElement ! : ElementRef ;
20
23
21
24
private defaultObserverOptions : IIntersectionObserverInit = {
22
25
root : null ,
23
26
rootMargin : '0px' ,
24
27
threshold : 0.2
25
28
} ;
26
29
27
- createIntersectionObserver ( hostElement : { nativeElement : Element ; } , observerOptions = this . defaultObserverOptions ) {
30
+ hostElementRefs : Map < ElementRef , IntersectionObserver | null > = new Map ( ) ;
28
31
29
- const options = { ...this . defaultObserverOptions , ...observerOptions } ;
32
+ createIntersectionObserver ( hostElement : ElementRef , observerOptions = this . defaultObserverOptions ) {
33
+
34
+ if ( isPlatformServer ( this . platformId ) ) {
35
+ this . #intersecting. next ( true ) ;
36
+ return ;
37
+ }
30
38
31
- this . hostElement = hostElement ;
39
+ // this.hostElement = hostElement;
40
+ const options = { ...this . defaultObserverOptions , ...observerOptions } ;
32
41
33
- const handleIntersect = ( entries : any [ ] , observer : any ) => {
42
+ const handleIntersect = ( entries : IntersectionObserverEntry [ ] , observer : IntersectionObserver ) => {
34
43
entries . forEach ( ( entry : any ) => {
35
- this . intersecting . next ( entry . isIntersecting ) ;
44
+ this . # intersecting. next ( entry . isIntersecting ) ;
36
45
} ) ;
37
46
} ;
38
47
39
- this . intersectionObserver = new IntersectionObserver ( handleIntersect , options ) ;
40
- this . intersectionObserver . observe ( hostElement . nativeElement ) ;
48
+ const intersectionObserver : IntersectionObserver = new IntersectionObserver ( handleIntersect , options ) ;
49
+ intersectionObserver . observe ( hostElement . nativeElement ) ;
50
+ this . hostElementRefs . set ( hostElement , intersectionObserver ) ;
51
+
52
+ }
53
+
54
+ unobserve ( elementRef : ElementRef ) {
55
+ this . hostElementRefs . get ( elementRef ) ?. unobserve ( elementRef . nativeElement ) ;
56
+ this . hostElementRefs . set ( elementRef , null ) ;
57
+ this . hostElementRefs . delete ( elementRef ) ;
41
58
}
42
59
43
60
ngOnDestroy ( ) : void {
44
- this . intersectionObserver ?. unobserve ( this . hostElement ?. nativeElement ) ;
61
+ this . hostElementRefs . forEach ( ( observer , elementRef ) => {
62
+ observer ?. unobserve ( elementRef . nativeElement ) ;
63
+ } ) ;
45
64
}
46
65
}
0 commit comments