11import {
22 AfterContentInit ,
33 Component ,
4+ DestroyRef ,
45 ElementRef ,
56 EventEmitter ,
67 HostBinding ,
8+ inject ,
79 Inject ,
810 Input ,
911 OnDestroy ,
1012 OnInit ,
1113 Output
1214} from '@angular/core' ;
13- import { fromEvent , Subscription , withLatestFrom , zipWith } from 'rxjs' ;
15+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop' ;
16+ import { finalize , fromEvent , Subscription , withLatestFrom , zipWith } from 'rxjs' ;
1417
1518import { IntersectionService } from '../../services/intersection.service' ;
1619import { IListenersConfig , ListenersService } from '../../services/listeners.service' ;
@@ -24,7 +27,7 @@ import { Triggers } from '../../coreui.types';
2427 selector : 'c-carousel' ,
2528 template : '<ng-content></ng-content>' ,
2629 styleUrls : [ './carousel.component.scss' ] ,
27- providers : [ CarouselService , CarouselState , CarouselConfig , IntersectionService , ListenersService ] ,
30+ providers : [ CarouselService , CarouselState , CarouselConfig , ListenersService ] ,
2831 standalone : true
2932} )
3033export class CarouselComponent implements OnInit , OnDestroy , AfterContentInit {
@@ -93,11 +96,10 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
9396 } ;
9497 }
9598
96- private carouselIndexSubscription ?: Subscription ;
9799 private timerId ! : any ;
98- private intersectingSubscription ?: Subscription ;
99100 private activeItemInterval = 0 ;
100101 private swipeSubscription ?: Subscription ;
102+ readonly #destroyRef = inject ( DestroyRef ) ;
101103
102104 constructor (
103105 @Inject ( CarouselConfig ) private config : CarouselConfig ,
@@ -116,13 +118,10 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
116118
117119 ngOnDestroy ( ) : void {
118120 this . clearListeners ( ) ;
119- this . carouselStateSubscribe ( false ) ;
120- this . intersectionServiceSubscribe ( false ) ;
121121 this . swipeSubscribe ( false ) ;
122122 }
123123
124124 ngAfterContentInit ( ) : void {
125- this . intersectionService . createIntersectionObserver ( this . hostElement ) ;
126125 this . intersectionServiceSubscribe ( ) ;
127126 this . carouselState . state = { activeItemIndex : this . activeIndex , animate : this . animate } ;
128127 this . setListeners ( ) ;
@@ -172,30 +171,34 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
172171 clearTimeout ( this . timerId ) ;
173172 }
174173
175- private carouselStateSubscribe ( subscribe : boolean = true ) : void {
176- if ( subscribe ) {
177- this . carouselIndexSubscription = this . carouselService . carouselIndex$ . subscribe ( ( nextItem ) => {
174+ private carouselStateSubscribe ( ) : void {
175+ this . carouselService . carouselIndex$
176+ . pipe (
177+ takeUntilDestroyed ( this . #destroyRef)
178+ )
179+ . subscribe ( ( nextItem ) => {
178180 if ( 'active' in nextItem ) {
179181 this . itemChange . emit ( nextItem . active ) ;
180182 }
181183 this . activeItemInterval = typeof nextItem . interval === 'number' && nextItem . interval > - 1 ? nextItem . interval : this . interval ;
182184 const isLastItem = ( ( nextItem . active === nextItem . lastItemIndex ) && this . direction === 'next' ) || ( ( nextItem . active === 0 ) && this . direction === 'prev' ) ;
183185 ! this . wrap && isLastItem ? this . resetTimer ( ) : this . setTimer ( ) ;
184186 } ) ;
185- } else {
186- this . carouselIndexSubscription ?. unsubscribe ( ) ;
187- }
188187 }
189188
190189 private intersectionServiceSubscribe ( subscribe : boolean = true ) : void {
191- if ( subscribe ) {
192- this . intersectingSubscription = this . intersectionService . intersecting$ . subscribe ( isIntersecting => {
190+ this . intersectionService . createIntersectionObserver ( this . hostElement ) ;
191+ this . intersectionService . intersecting$
192+ . pipe (
193+ finalize ( ( ) => {
194+ this . intersectionService . unobserve ( this . hostElement ) ;
195+ } ) ,
196+ takeUntilDestroyed ( this . #destroyRef)
197+ )
198+ . subscribe ( isIntersecting => {
193199 this . visible = isIntersecting ;
194200 isIntersecting ? this . setTimer ( ) : this . resetTimer ( ) ;
195201 } ) ;
196- } else {
197- this . intersectingSubscription ?. unsubscribe ( ) ;
198- }
199202 }
200203
201204 private swipeSubscribe ( subscribe : boolean = true ) : void {
@@ -204,7 +207,10 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
204207 const touchStart$ = fromEvent < TouchEvent > ( carouselElement , 'touchstart' ) ;
205208 const touchEnd$ = fromEvent < TouchEvent > ( carouselElement , 'touchend' ) ;
206209 const touchMove$ = fromEvent < TouchEvent > ( carouselElement , 'touchmove' ) ;
207- this . swipeSubscription = touchStart$ . pipe ( zipWith ( touchEnd$ . pipe ( withLatestFrom ( touchMove$ ) ) ) )
210+ this . swipeSubscription = touchStart$ . pipe (
211+ zipWith ( touchEnd$ . pipe ( withLatestFrom ( touchMove$ ) ) ) ,
212+ takeUntilDestroyed ( this . #destroyRef)
213+ )
208214 . subscribe ( ( [ touchstart , [ touchend , touchmove ] ] ) => {
209215 touchstart . stopPropagation ( ) ;
210216 touchmove . stopPropagation ( ) ;
0 commit comments