@@ -15,6 +15,7 @@ import {
1515 IterableChanges ,
1616 IterableDiffer ,
1717 IterableDiffers ,
18+ NgIterable ,
1819 NgZone ,
1920 OnDestroy ,
2021 OnInit ,
@@ -46,7 +47,7 @@ import { NguCarouselHammerManager } from './ngu-carousel-hammer-manager';
4647
4748type DirectionSymbol = '' | '-' ;
4849
49- type NguCarouselDataSource = Observable < any [ ] > | any [ ] | null | undefined ;
50+ type NguCarouselDataSource < T , U > = ( U & NgIterable < T > ) | null | undefined ;
5051
5152// This will be provided through Terser global definitions by Angular CLI.
5253// This is how Angular does tree-shaking internally.
@@ -62,9 +63,9 @@ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
6263 providers : [ NguCarouselHammerManager ]
6364} )
6465// eslint-disable-next-line @angular-eslint/component-class-suffix
65- export class NguCarousel < T >
66+ export class NguCarousel < T , U extends NgIterable < T > = NgIterable < T > >
6667 extends NguCarouselStore
67- implements OnInit , AfterContentInit , AfterViewInit , OnDestroy , DoCheck
68+ implements AfterContentInit , AfterViewInit , OnDestroy , DoCheck
6869{
6970 /** Public property that may be accessed outside of the component. */
7071 activePoint = 0 ;
@@ -77,28 +78,18 @@ export class NguCarousel<T>
7778 // eslint-disable-next-line @angular-eslint/no-output-on-prefix
7879 @Output ( ) onMove = new EventEmitter < NguCarousel < T > > ( ) ;
7980
80- private _arrayChanges : IterableChanges < { } > | null = null ;
81+ private _arrayChanges : IterableChanges < T > | null = null ;
8182
8283 @Input ( )
83- get dataSource ( ) : NguCarouselDataSource {
84+ get dataSource ( ) : NguCarouselDataSource < T , U > {
8485 return this . _dataSource ;
8586 }
86- set dataSource ( data : NguCarouselDataSource ) {
87+ set dataSource ( data : NguCarouselDataSource < T , U > ) {
8788 if ( data ) {
8889 this . _switchDataSource ( data ) ;
8990 }
9091 }
91- private _dataSource : NguCarouselDataSource = null ;
92-
93- /**
94- * `_dataSource` allows multiple values to be set considering nullable and
95- * observable values. We shouldn't try to get `_dataSource.length` since it
96- * might be `null|undefined` which will throw an error that property doesn't
97- * exist on `undefined`. It will also always equal `undefined` on observable.
98- * We should wait until the observable is unwrapped and then check the length
99- * of the actual unwrapped data.
100- */
101- private _unwrappedData : any [ ] = [ ] ;
92+ private _dataSource : NguCarouselDataSource < T , U > = null ;
10293
10394 private _defaultNodeDef : NguCarouselDefDirective < any > | null ;
10495
@@ -145,14 +136,16 @@ export class NguCarousel<T>
145136
146137 private _carouselCssNode : HTMLStyleElement ;
147138
148- private _dataDiffer : IterableDiffer < { } > ;
139+ private _dataDiffer : IterableDiffer < T > ;
149140
150141 private _styleid : string ;
151142
152143 private _pointIndex : number ;
153144
154145 private _destroy$ = new Subject < void > ( ) ;
155146
147+ private ngu_dirty : boolean = true ;
148+
156149 /**
157150 * Tracking function that will be used to check the differences in data changes. Used similarly
158151 * to `ngFor` `trackBy` function. Optimize Items operations by identifying a Items based on its data
@@ -189,47 +182,32 @@ export class NguCarousel<T>
189182 this . _setupButtonListeners ( ) ;
190183 }
191184
192- ngOnInit ( ) {
193- this . _dataDiffer = this . _differs
194- . find ( [ ] )
195- . create ( ( index : number , item : any ) => ( this . trackBy ? this . trackBy ( index , item ) : item ) ) ;
196- }
197-
198185 ngDoCheck ( ) {
199- this . _arrayChanges = this . _dataDiffer . diff ( this . _unwrappedData ) ! ;
200- if ( this . _arrayChanges && this . _defDirectives ) {
201- this . _observeRenderChanges ( ) ;
186+ if ( this . ngu_dirty ) {
187+ this . ngu_dirty = false ;
188+ const dataStream = this . _dataSource ;
189+ if ( ! this . _arrayChanges && ! ! dataStream ) {
190+ this . _dataDiffer = this . _differs
191+ . find ( dataStream )
192+ . create ( ( index : number , item : any ) => ( this . trackBy ? this . trackBy ( index , item ) : item ) ) ! ;
193+ }
194+ }
195+ if ( this . _dataDiffer && this . _defDirectives ) {
196+ this . _arrayChanges = this . _dataDiffer . diff ( this . _dataSource ) ! ;
197+ if ( this . _arrayChanges ) {
198+ this . renderNodeChanges ( Array . from ( this . _dataSource ! ) ) ;
199+ }
202200 }
203201 }
204202
205203 private _switchDataSource ( dataSource : any ) : any {
206204 this . _dataSource = dataSource ;
207- if ( this . _defDirectives ) {
208- this . _observeRenderChanges ( ) ;
209- }
210- }
211-
212- private _observeRenderChanges ( ) {
213- let dataStream : Observable < any [ ] > | undefined ;
214-
215- if ( this . _dataSource instanceof Observable ) {
216- dataStream = this . _dataSource ;
217- } else if ( Array . isArray ( this . _dataSource ) ) {
218- dataStream = of ( this . _dataSource ) ;
219- }
220-
221- dataStream
222- ?. pipe ( takeUntil ( merge ( this . _intervalController$ , this . _destroy$ ) ) )
223- . subscribe ( data => {
224- this . _unwrappedData = data ;
225- this . renderNodeChanges ( data ) ;
226- this . isLast = this . _pointIndex === this . currentSlide ;
227- } ) ;
205+ this . ngu_dirty = true ;
228206 }
229207
230208 private renderNodeChanges ( data : any [ ] ) {
231209 if ( ! this . _arrayChanges ) return ;
232-
210+ this . isLast = this . _pointIndex === this . currentSlide ;
233211 const viewContainer = this . _nodeOutlet . viewContainer ;
234212
235213 this . _arrayChanges . forEachOperation (
@@ -304,8 +282,6 @@ export class NguCarousel<T>
304282 }
305283
306284 ngAfterContentInit ( ) {
307- this . _observeRenderChanges ( ) ;
308-
309285 this . _cdr . markForCheck ( ) ;
310286 }
311287
@@ -507,7 +483,7 @@ export class NguCarousel<T>
507483
508484 /** Init carousel point */
509485 private _carouselPoint ( ) : void {
510- const Nos = this . _unwrappedData . length - ( this . items - this . slideItems ) ;
486+ const Nos = Array . from ( this . _dataSource ! ) . length - ( this . items - this . slideItems ) ;
511487 this . _pointIndex = Math . ceil ( Nos / this . slideItems ) ;
512488 const pointers : number [ ] = [ ] ;
513489
@@ -552,7 +528,7 @@ export class NguCarousel<T>
552528 break ;
553529 case this . _pointIndex - 1 :
554530 this . _btnBoolean ( 0 , 1 ) ;
555- slideremains = this . _unwrappedData . length - this . items ;
531+ slideremains = Array . from ( this . _dataSource ! ) . length - this . items ;
556532 break ;
557533 default :
558534 this . _btnBoolean ( 0 , 0 ) ;
@@ -665,7 +641,7 @@ export class NguCarousel<T>
665641 const MoveSlide = currentSlideD + this . slideItems ;
666642 this . _btnBoolean ( 0 , 1 ) ;
667643 if ( this . currentSlide === 0 ) {
668- currentSlide = this . _unwrappedData . length - this . items ;
644+ currentSlide = Array . from ( this . _dataSource ! ) . length - this . items ;
669645 itemSpeed = 400 ;
670646 this . _btnBoolean ( 0 , 1 ) ;
671647 } else if ( this . slideItems >= MoveSlide ) {
@@ -683,10 +659,10 @@ export class NguCarousel<T>
683659 this . _carouselScrollTwo ( Btn , currentSlide , itemSpeed ) ;
684660 } else if ( Btn === 1 && ( ( ! this . loop && ! this . isLast ) || this . loop ) ) {
685661 if (
686- this . _unwrappedData . length <= this . currentSlide + this . items + this . slideItems &&
662+ Array . from ( this . _dataSource ! ) . length <= this . currentSlide + this . items + this . slideItems &&
687663 ! this . isLast
688664 ) {
689- currentSlide = this . _unwrappedData . length - this . items ;
665+ currentSlide = Array . from ( this . _dataSource ! ) . length - this . items ;
690666 this . _btnBoolean ( 0 , 1 ) ;
691667 } else if ( this . isLast ) {
692668 currentSlide = 0 ;
@@ -732,7 +708,7 @@ export class NguCarousel<T>
732708 this . _setStyle ( this . _nguItemsContainer . nativeElement , 'transition' , `` ) ;
733709 }
734710
735- this . itemLength = this . _unwrappedData . length ;
711+ this . itemLength = Array . from ( this . _dataSource ! ) . length ;
736712 this . _transformStyle ( currentSlide ) ;
737713 this . currentSlide = currentSlide ;
738714 this . onMove . emit ( this ) ;
@@ -785,7 +761,7 @@ export class NguCarousel<T>
785761 /** this will trigger the carousel to load the items */
786762 private _carouselLoadTrigger ( ) : void {
787763 if ( typeof this . inputs . load === 'number' ) {
788- this . _unwrappedData . length - this . load <= this . currentSlide + this . items &&
764+ Array . from ( this . _dataSource ! ) . length - this . load <= this . currentSlide + this . items &&
789765 this . carouselLoad . emit ( this . currentSlide ) ;
790766 }
791767 }
@@ -957,5 +933,5 @@ export class NguCarousel<T>
957933 ) ;
958934 }
959935
960- static ngAcceptInputType_dataSource : NguCarouselDataSource ;
936+ static ngAcceptInputType_dataSource : NguCarouselDataSource < any , any > ;
961937}
0 commit comments