@@ -208,7 +208,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
208
208
209
209
/**
210
210
* @input {array} The data that builds the templates within the virtual scroll.
211
- * This is the same data that you'd pass to `ngFor`. It's important to note
211
+ * This is the same data that you'd pass to `* ngFor`. It's important to note
212
212
* that when this data has changed, then the entire virtual scroll is reset,
213
213
* which is an expensive operation and should be avoided if possible.
214
214
*/
@@ -225,12 +225,12 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
225
225
* should get created when initially rendered. The number is a
226
226
* multiplier against the viewable area's height. For example, if it
227
227
* takes `20` cells to fill up the height of the viewable area, then
228
- * with a buffer ratio of `2 ` it will create `40 ` cells that are
228
+ * with a buffer ratio of `3 ` it will create `60 ` cells that are
229
229
* available for reuse while scrolling. For better performance, it's
230
230
* better to have more cells than what are required to fill the
231
- * viewable area. Default is `2 `.
231
+ * viewable area. Default is `3 `.
232
232
*/
233
- @Input ( ) bufferRatio : number = 2 ;
233
+ @Input ( ) bufferRatio : number = 3 ;
234
234
235
235
/**
236
236
* @input {string} The approximate width of each item template's cell.
@@ -239,20 +239,22 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
239
239
* the scrollable area. This value can use either `px` or `%` units.
240
240
* Note that the actual rendered size of each cell comes from the
241
241
* app's CSS, whereas this approximation is used to help calculate
242
- * initial dimensions. Default is `100%`.
242
+ * initial dimensions before the item has been rendered. Default is
243
+ * `100%`.
243
244
*/
244
245
@Input ( ) approxItemWidth : string = '100%' ;
245
246
246
247
/**
247
- * @input {string} Default is `40px`. It is important to provide this
248
+ * @input {string} It is important to provide this
248
249
* if virtual item height will be significantly larger than the default
249
250
* The approximate height of each virtual item template's cell.
250
251
* This dimension is used to help determine how many cells should
251
252
* be created when initialized, and to help calculate the height of
252
253
* the scrollable area. This height value can only use `px` units.
253
254
* Note that the actual rendered size of each cell comes from the
254
255
* app's CSS, whereas this approximation is used to help calculate
255
- * initial dimensions.
256
+ * initial dimensions before the item has been rendered. Default is
257
+ * `40px`.
256
258
*/
257
259
@Input ( ) approxItemHeight : string ;
258
260
@@ -274,7 +276,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
274
276
* the scrollable area. This height value can only use `px` units.
275
277
* Note that the actual rendered size of each cell comes from the
276
278
* app's CSS, whereas this approximation is used to help calculate
277
- * initial dimensions. Default is `40px`.
279
+ * initial dimensions before the item has been rendered . Default is `40px`.
278
280
*/
279
281
@Input ( ) approxHeaderHeight : string = '40px' ;
280
282
@@ -285,7 +287,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
285
287
* the scrollable area. This value can use either `px` or `%` units.
286
288
* Note that the actual rendered size of each cell comes from the
287
289
* app's CSS, whereas this approximation is used to help calculate
288
- * initial dimensions. Default is `100%`.
290
+ * initial dimensions before the item has been rendered . Default is `100%`.
289
291
*/
290
292
@Input ( ) approxFooterWidth : string = '100%' ;
291
293
@@ -296,7 +298,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
296
298
* the scrollable area. This height value can only use `px` units.
297
299
* Note that the actual rendered size of each cell comes from the
298
300
* app's CSS, whereas this approximation is used to help calculate
299
- * initial dimensions. Default is `40px`.
301
+ * initial dimensions before the item has been rendered . Default is `40px`.
300
302
*/
301
303
@Input ( ) approxFooterHeight : string = '40px' ;
302
304
@@ -345,7 +347,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
345
347
private _content : Content ,
346
348
private _platform : Platform ,
347
349
@Optional ( ) private _ctrl : ViewController ,
348
- config : Config ,
350
+ private _config : Config ,
349
351
private _dom : DomController ) {
350
352
351
353
// hide the virtual scroll element with opacity so we don't
@@ -355,6 +357,8 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
355
357
356
358
// wait for the content to be rendered and has readable dimensions
357
359
_content . readReady . subscribe ( ( ) => {
360
+ this . _init = true ;
361
+
358
362
if ( this . _hasChanges ( ) ) {
359
363
this . readUpdate ( ) ;
360
364
@@ -363,15 +367,24 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
363
367
subscription . unsubscribe ( ) ;
364
368
this . writeUpdate ( ) ;
365
369
} ) ;
366
-
367
- if ( ! this . _scrollSub ) {
368
- // listen for scroll events
369
- this . addScrollListener ( config . getBoolean ( 'virtualScrollEventAssist' ) ) ;
370
- }
371
370
}
371
+
372
+ this . _listeners ( ) ;
372
373
} ) ;
373
374
}
374
375
376
+ /**
377
+ * @private
378
+ */
379
+ ngDoCheck ( ) {
380
+ if ( this . _init && this . _hasChanges ( ) ) {
381
+ // only continue if we've already initialized
382
+ // and if there actually are changes
383
+ this . readUpdate ( ) ;
384
+ this . writeUpdate ( ) ;
385
+ }
386
+ }
387
+
375
388
readUpdate ( ) {
376
389
console . debug ( `virtual-scroll, readUpdate` ) ;
377
390
@@ -406,37 +419,6 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
406
419
return ( isPresent ( this . _records ) && isPresent ( this . _differ ) && isPresent ( this . _differ . diff ( this . _records ) ) ) ;
407
420
}
408
421
409
- /**
410
- * @private
411
- */
412
- ngDoCheck ( ) {
413
- if ( this . _init && this . _hasChanges ( ) ) {
414
- // only continue if we've already initialized
415
- // and if there actually are changes
416
- this . readUpdate ( ) ;
417
- this . writeUpdate ( ) ;
418
- }
419
- }
420
-
421
- /**
422
- * @private
423
- */
424
- ngAfterContentInit ( ) {
425
- if ( ! this . _init ) {
426
-
427
- if ( ! this . _itmTmp ) {
428
- throw 'virtualItem required within virtualScroll' ;
429
- }
430
-
431
- this . _init = true ;
432
-
433
- if ( ! this . approxItemHeight ) {
434
- this . approxItemHeight = '40px' ;
435
- console . warn ( 'Virtual Scroll: Please provide an "approxItemHeight" input to ensure proper virtual scroll rendering' ) ;
436
- }
437
- }
438
- }
439
-
440
422
/**
441
423
* @private
442
424
* DOM WRITE
@@ -502,7 +484,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
502
484
writeToNodes ( nodes , cells , recordsLength ) ;
503
485
504
486
// ******** DOM WRITE ****************
505
- this . setVirtualHeight (
487
+ this . _setHeight (
506
488
estimateHeight ( recordsLength , cells [ cells . length - 1 ] , this . _vHeight , 0.25 )
507
489
) ;
508
490
@@ -525,13 +507,14 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
525
507
data . scrollTop = ev . scrollTop ;
526
508
527
509
if ( this . _queue === ScrollQueue . RequiresDomWrite ) {
510
+ // there are DOM writes we need to take care of in this frame
528
511
529
512
this . _dom . write ( ( ) => {
530
513
// ******** DOM WRITE ****************
531
514
writeToNodes ( nodes , cells , this . _records . length ) ;
532
515
533
516
// ******** DOM WRITE ****************
534
- this . setVirtualHeight (
517
+ this . _setHeight (
535
518
estimateHeight ( this . _records . length , cells [ cells . length - 1 ] , this . _vHeight , 0.25 )
536
519
) ;
537
520
@@ -540,6 +523,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
540
523
} ) ;
541
524
542
525
} else if ( this . _queue === ScrollQueue . RequiresChangeDetection ) {
526
+ // we need to do some change detection in this frame
543
527
544
528
this . _dom . write ( ( ) => {
545
529
// we've got work painting do, let's throw it in the
@@ -556,7 +540,8 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
556
540
} ) ;
557
541
558
542
} else {
559
-
543
+ // no dom writes or change detection to take care of
544
+ // let's see if we've scroll far enough to require another check
560
545
data . scrollDiff = ( data . scrollTop - this . _lastCheck ) ;
561
546
562
547
if ( Math . abs ( data . scrollDiff ) > SCROLL_DIFFERENCE_MINIMUM ) {
@@ -625,7 +610,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
625
610
writeToNodes ( nodes , cells , this . _records . length ) ;
626
611
627
612
// ******** DOM WRITE ****************
628
- this . setVirtualHeight (
613
+ this . _setHeight (
629
614
estimateHeight ( this . _records . length , cells [ cells . length - 1 ] , this . _vHeight , 0.05 )
630
615
) ;
631
616
@@ -634,10 +619,9 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
634
619
}
635
620
636
621
/**
637
- * @private
638
622
* DOM WRITE
639
623
*/
640
- setVirtualHeight ( newVirtualHeight : number ) {
624
+ private _setHeight ( newVirtualHeight : number ) {
641
625
if ( newVirtualHeight !== this . _vHeight ) {
642
626
// ******** DOM WRITE ****************
643
627
this . _renderer . setElementStyle ( this . _elementRef . nativeElement , 'height' , newVirtualHeight > 0 ? newVirtualHeight + 'px' : '' ) ;
@@ -647,31 +631,42 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
647
631
}
648
632
}
649
633
634
+ private _listeners ( ) {
635
+ if ( ! this . _scrollSub ) {
636
+ if ( this . _config . getBoolean ( 'virtualScrollEventAssist' ) ) {
637
+ // use JS scrolling for iOS UIWebView
638
+ // goal is to completely remove this when iOS
639
+ // fully supports scroll events
640
+ // listen to JS scroll events
641
+ this . _content . enableJsScroll ( ) ;
642
+ }
643
+
644
+ this . _scrollSub = this . _content . ionScroll . subscribe ( ( ev : ScrollEvent ) => {
645
+ this . scrollUpdate ( ev ) ;
646
+ } ) ;
647
+
648
+ this . _scrollEndSub = this . _content . ionScrollEnd . subscribe ( ( ev : ScrollEvent ) => {
649
+ this . scrollEnd ( ev ) ;
650
+ } ) ;
651
+ }
652
+ }
653
+
650
654
/**
651
655
* @private
652
- * NO DOM
653
656
*/
654
- addScrollListener ( eventAssist : boolean ) {
655
- if ( eventAssist ) {
656
- // use JS scrolling for iOS UIWebView
657
- // goal is to completely remove this when iOS
658
- // fully supports scroll events
659
- // listen to JS scroll events
660
- this . _content . enableJsScroll ( ) ;
657
+ ngAfterContentInit ( ) {
658
+ if ( ! this . _itmTmp ) {
659
+ throw 'virtualItem required within virtualScroll' ;
661
660
}
662
661
663
- this . _scrollSub = this . _content . ionScroll . subscribe ( ( ev : ScrollEvent ) => {
664
- this . scrollUpdate ( ev ) ;
665
- } ) ;
666
-
667
- this . _scrollEndSub = this . _content . ionScrollEnd . subscribe ( ( ev : ScrollEvent ) => {
668
- this . scrollEnd ( ev ) ;
669
- } ) ;
662
+ if ( ! this . approxItemHeight ) {
663
+ this . approxItemHeight = '40px' ;
664
+ console . warn ( 'Virtual Scroll: Please provide an "approxItemHeight" input to ensure proper virtual scroll rendering' ) ;
665
+ }
670
666
}
671
667
672
668
/**
673
669
* @private
674
- * NO DOM
675
670
*/
676
671
ngOnDestroy ( ) {
677
672
this . _scrollSub && this . _scrollSub . unsubscribe ( ) ;
@@ -680,7 +675,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
680
675
681
676
}
682
677
683
- const SCROLL_DIFFERENCE_MINIMUM = 20 ;
678
+ const SCROLL_DIFFERENCE_MINIMUM = 40 ;
684
679
685
680
export const enum ScrollQueue {
686
681
NoChanges ,
0 commit comments