Skip to content

Commit

Permalink
fix(ngrid): fixed virtual scroll wrong offset on filter
Browse files Browse the repository at this point in the history
Fixes #11
  • Loading branch information
shlomiassaf committed Jun 23, 2019
1 parent c6ca3e5 commit 56ff95f
Showing 1 changed file with 55 additions and 3 deletions.
58 changes: 55 additions & 3 deletions libs/ngrid/src/lib/table/features/virtual-scroll/strategies.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Observable } from 'rxjs';
import { Directive, Input, OnInit, OnChanges, ElementRef } from '@angular/core';

import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
import { coerceNumberProperty } from '@angular/cdk/coercion';
import { ListRange } from '@angular/cdk/collections';
import { CdkVirtualScrollViewport, FixedSizeVirtualScrollStrategy, VirtualScrollStrategy, VIRTUAL_SCROLL_STRATEGY } from '@angular/cdk/scrolling';
import { AutoSizeVirtualScrollStrategy, ItemSizeAverager } from '@angular/cdk-experimental/scrolling';

import { PblNgridComponent } from '../../table.component';
import { NgeVirtualTableRowInfo } from './virtual-scroll-for-of';
import { P } from '@angular/cdk/keycodes';

const noop = function(nv?: any, nv1?: any) { };

Expand Down Expand Up @@ -48,6 +49,57 @@ export class TableItemSizeAverager extends ItemSizeAverager {
}
}

export class PblNgridFixedSizeVirtualScrollStrategy extends FixedSizeVirtualScrollStrategy {

private _ngridViewport: CdkVirtualScrollViewport;

constructor(private itemSize: number, minBufferPx: number, maxBufferPx: number) {
super(itemSize, minBufferPx, maxBufferPx);
}

attach(viewport: CdkVirtualScrollViewport) {
super.attach(this._ngridViewport = viewport);
}

onContentScrolled() {
// https://github.com/shlomiassaf/ngrid/issues/11

// This is a workaround an issue with FixedSizeVirtualScrollStrategy
// When:
// - The rendered data is changed so the data length is now LOWER then the current range (end - start)
// - The rendering direction is towards the top (start > end)
//
// For the issue to occur a big gap between the data length and the range length (gap), which does not happen on normal scrolling
// but only when the data source is replaced (e.g. filtering).
//
// In such cases `onDataLengthChanged` is called which will call `_updateRenderedRange` which will calculate a new range
// that is big, it will give the `start` a new value which creates the big gap.
// It will then calculate a new "end" and leave the "start" so we have a big gap, larger then the viewport size.
// After that it will create the new offset which is the itemSize * start, which is a bit lower then the offset but is large and again does not fit the viewport size
// The scroll change will trigger `onContentScrolled` which will call `_updateRenderedRange` again,
// with the same outcome, reducing the offset slightly, calling `onContentScrolled` again.
// It will repeat until reaching the proper offset.
//
// The amount of offset reduced each time is approx the size of the buffers. (mix/max Buffer).
//
// This strategy is here only because of this error, it will let the initial update run and catch it's subsequent scroll event.
if (!this._ngridViewport) {
return;
}
let { start, end } = this._ngridViewport.getRenderedRange();
const rangeLength = end - start;
const dataLength = this._ngridViewport.getDataLength();
if (rangeLength < 0 && dataLength < -rangeLength) {
start = dataLength - end;
this._ngridViewport.setRenderedRange({ start, end });
this._ngridViewport.setRenderedContentOffset(this.itemSize * start);
// this._scrolledIndexChange.next(Math.floor(firstVisibleIndex));
} else {
super.onContentScrolled();
}
}
}

export class TableAutoSizeVirtualScrollStrategy extends AutoSizeVirtualScrollStrategy {
constructor(minBufferPx: number, maxBufferPx: number, public readonly averager = new TableItemSizeAverager()) {
super(minBufferPx, maxBufferPx, averager);
Expand Down Expand Up @@ -147,7 +199,7 @@ export class PblCdkVirtualScrollDirective implements OnInit, OnChanges, VirtualS
if (!this._vScrollFixed) {
this.vScrollFixed = this.table.findInitialRowHeight() || 48;
}
this._scrollStrategy = new FixedSizeVirtualScrollStrategy(this.vScrollFixed, this.minBufferPx, this.maxBufferPx);
this._scrollStrategy = new PblNgridFixedSizeVirtualScrollStrategy(this.vScrollFixed, this.minBufferPx, this.maxBufferPx);
break;
case 'vScrollAuto':
if (!this._vScrollAuto) {
Expand All @@ -165,7 +217,7 @@ export class PblCdkVirtualScrollDirective implements OnInit, OnChanges, VirtualS
if (this._scrollStrategy) {
switch (this.type) {
case 'vScrollFixed':
(this._scrollStrategy as FixedSizeVirtualScrollStrategy)
(this._scrollStrategy as PblNgridFixedSizeVirtualScrollStrategy)
.updateItemAndBufferSize(this.vScrollFixed, this.minBufferPx, this.maxBufferPx);
break;
case 'vScrollAuto':
Expand Down

0 comments on commit 56ff95f

Please sign in to comment.