@@ -15,6 +15,7 @@ import {
15
15
IterableChanges ,
16
16
IterableDiffer ,
17
17
IterableDiffers ,
18
+ NgIterable ,
18
19
NgZone ,
19
20
OnDestroy ,
20
21
OnInit ,
@@ -46,7 +47,7 @@ import { NguCarouselHammerManager } from './ngu-carousel-hammer-manager';
46
47
47
48
type DirectionSymbol = '' | '-' ;
48
49
49
- type NguCarouselDataSource = Observable < any [ ] > | any [ ] | null | undefined ;
50
+ type NguCarouselDataSource < T , U > = ( U & NgIterable < T > ) | null | undefined ;
50
51
51
52
// This will be provided through Terser global definitions by Angular CLI.
52
53
// This is how Angular does tree-shaking internally.
@@ -62,9 +63,9 @@ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
62
63
providers : [ NguCarouselHammerManager ]
63
64
} )
64
65
// 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 > >
66
67
extends NguCarouselStore
67
- implements OnInit , AfterContentInit , AfterViewInit , OnDestroy , DoCheck
68
+ implements AfterContentInit , AfterViewInit , OnDestroy , DoCheck
68
69
{
69
70
/** Public property that may be accessed outside of the component. */
70
71
activePoint = 0 ;
@@ -77,28 +78,18 @@ export class NguCarousel<T>
77
78
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
78
79
@Output ( ) onMove = new EventEmitter < NguCarousel < T > > ( ) ;
79
80
80
- private _arrayChanges : IterableChanges < { } > | null = null ;
81
+ private _arrayChanges : IterableChanges < T > | null = null ;
81
82
82
83
@Input ( )
83
- get dataSource ( ) : NguCarouselDataSource {
84
+ get dataSource ( ) : NguCarouselDataSource < T , U > {
84
85
return this . _dataSource ;
85
86
}
86
- set dataSource ( data : NguCarouselDataSource ) {
87
+ set dataSource ( data : NguCarouselDataSource < T , U > ) {
87
88
if ( data ) {
88
89
this . _switchDataSource ( data ) ;
89
90
}
90
91
}
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 ;
102
93
103
94
private _defaultNodeDef : NguCarouselDefDirective < any > | null ;
104
95
@@ -145,14 +136,16 @@ export class NguCarousel<T>
145
136
146
137
private _carouselCssNode : HTMLStyleElement ;
147
138
148
- private _dataDiffer : IterableDiffer < { } > ;
139
+ private _dataDiffer : IterableDiffer < T > ;
149
140
150
141
private _styleid : string ;
151
142
152
143
private _pointIndex : number ;
153
144
154
145
private _destroy$ = new Subject < void > ( ) ;
155
146
147
+ private ngu_dirty : boolean = true ;
148
+
156
149
/**
157
150
* Tracking function that will be used to check the differences in data changes. Used similarly
158
151
* to `ngFor` `trackBy` function. Optimize Items operations by identifying a Items based on its data
@@ -189,47 +182,32 @@ export class NguCarousel<T>
189
182
this . _setupButtonListeners ( ) ;
190
183
}
191
184
192
- ngOnInit ( ) {
193
- this . _dataDiffer = this . _differs
194
- . find ( [ ] )
195
- . create ( ( index : number , item : any ) => ( this . trackBy ? this . trackBy ( index , item ) : item ) ) ;
196
- }
197
-
198
185
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
+ }
202
200
}
203
201
}
204
202
205
203
private _switchDataSource ( dataSource : any ) : any {
206
204
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 ;
228
206
}
229
207
230
208
private renderNodeChanges ( data : any [ ] ) {
231
209
if ( ! this . _arrayChanges ) return ;
232
-
210
+ this . isLast = this . _pointIndex === this . currentSlide ;
233
211
const viewContainer = this . _nodeOutlet . viewContainer ;
234
212
235
213
this . _arrayChanges . forEachOperation (
@@ -304,8 +282,6 @@ export class NguCarousel<T>
304
282
}
305
283
306
284
ngAfterContentInit ( ) {
307
- this . _observeRenderChanges ( ) ;
308
-
309
285
this . _cdr . markForCheck ( ) ;
310
286
}
311
287
@@ -507,7 +483,7 @@ export class NguCarousel<T>
507
483
508
484
/** Init carousel point */
509
485
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 ) ;
511
487
this . _pointIndex = Math . ceil ( Nos / this . slideItems ) ;
512
488
const pointers : number [ ] = [ ] ;
513
489
@@ -552,7 +528,7 @@ export class NguCarousel<T>
552
528
break ;
553
529
case this . _pointIndex - 1 :
554
530
this . _btnBoolean ( 0 , 1 ) ;
555
- slideremains = this . _unwrappedData . length - this . items ;
531
+ slideremains = Array . from ( this . _dataSource ! ) . length - this . items ;
556
532
break ;
557
533
default :
558
534
this . _btnBoolean ( 0 , 0 ) ;
@@ -665,7 +641,7 @@ export class NguCarousel<T>
665
641
const MoveSlide = currentSlideD + this . slideItems ;
666
642
this . _btnBoolean ( 0 , 1 ) ;
667
643
if ( this . currentSlide === 0 ) {
668
- currentSlide = this . _unwrappedData . length - this . items ;
644
+ currentSlide = Array . from ( this . _dataSource ! ) . length - this . items ;
669
645
itemSpeed = 400 ;
670
646
this . _btnBoolean ( 0 , 1 ) ;
671
647
} else if ( this . slideItems >= MoveSlide ) {
@@ -683,10 +659,10 @@ export class NguCarousel<T>
683
659
this . _carouselScrollTwo ( Btn , currentSlide , itemSpeed ) ;
684
660
} else if ( Btn === 1 && ( ( ! this . loop && ! this . isLast ) || this . loop ) ) {
685
661
if (
686
- this . _unwrappedData . length <= this . currentSlide + this . items + this . slideItems &&
662
+ Array . from ( this . _dataSource ! ) . length <= this . currentSlide + this . items + this . slideItems &&
687
663
! this . isLast
688
664
) {
689
- currentSlide = this . _unwrappedData . length - this . items ;
665
+ currentSlide = Array . from ( this . _dataSource ! ) . length - this . items ;
690
666
this . _btnBoolean ( 0 , 1 ) ;
691
667
} else if ( this . isLast ) {
692
668
currentSlide = 0 ;
@@ -732,7 +708,7 @@ export class NguCarousel<T>
732
708
this . _setStyle ( this . _nguItemsContainer . nativeElement , 'transition' , `` ) ;
733
709
}
734
710
735
- this . itemLength = this . _unwrappedData . length ;
711
+ this . itemLength = Array . from ( this . _dataSource ! ) . length ;
736
712
this . _transformStyle ( currentSlide ) ;
737
713
this . currentSlide = currentSlide ;
738
714
this . onMove . emit ( this ) ;
@@ -785,7 +761,7 @@ export class NguCarousel<T>
785
761
/** this will trigger the carousel to load the items */
786
762
private _carouselLoadTrigger ( ) : void {
787
763
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 &&
789
765
this . carouselLoad . emit ( this . currentSlide ) ;
790
766
}
791
767
}
@@ -957,5 +933,5 @@ export class NguCarousel<T>
957
933
) ;
958
934
}
959
935
960
- static ngAcceptInputType_dataSource : NguCarouselDataSource ;
936
+ static ngAcceptInputType_dataSource : NguCarouselDataSource < any , any > ;
961
937
}
0 commit comments