Maintain scroll position with CDK autosize virtual scroll strategy
I have a large list of items that can be scrolled with <cdk-virtual-scroll-viewport autosize>
provided by @angular/cdk-experimental
(the items have dynamic heights, thus I'm using this scroll strategy instead of the FixedSizeVirtualScrollStrategy
).
New items are inserted in the list over time, i.e. they are appended on top. When the user scrolls down I want to avoid that new items will push the items in the viewport away. Therefore I need a mechanism to maintain / restore the scroll position after the items have been added.
I have a semi-working solution (and hacky because it reads private fields), but the viewport shifts a few pixels randomly after items have been added.
Here are the relevant code parts:
@ViewChild(CdkVirtualScrollViewport) viewport: CdkVirtualScrollViewport;
...
// After new items have been added:
const offset = this.viewport.measureScrollOffset('top');
const topPosition = offset + newItems.length * this.viewport['_scrollStrategy']._averager._averageItemSize; // the autosize strategy determines an average item size I'm trying to use to determine how the viewport should be shifted
this.viewport.scrollTo({
top: topPosition
});
I created a demo of this approach here: https://stackblitz.com/edit/angular-be926g?file=src/app/cdk-virtual-scroll-overview-example.ts
Any ideas how to achieve this seamlessly with a constant viewport?
This feature is added to CDK (Component Development Kit). Virtual scrolling shows up the visible dom elements to the user, as the user scrolls, the next list is displayed. This gives faster experience as the full list is not loaded at one go and only loaded as per the visibility on the screen.
[itemSize] dictates how tall in pixels each row in the list is. The virtual scroller then uses this (in part) to determine how many rows it can buffer above and below the viewport. The less tall you make the itemSize , the more it will try to load and buffer.
Scrolling over fixed size items When all items are the same fixed size, you can use the FixedSizeVirtualScrollStrategy . This can be easily added to your viewport using the itemSize directive.
Virtual scrolling allows the Grid component to display thousands of records on a single page. You can use this feature as an alternative to paging. Browser Support Notes: The following browsers do not support virtual scrolling because they do not support position: sticky : Android Browser before 5.0.
you can use this.viewport.getRenderedRange()
to check the viewport is on top and if zero then append the elements else keep the elements in a bucket and append the objects when user scrolled to top of viewport.
const range = this.viewport.getRenderedRange();
console.log("range", range);
bucket = [...bucket, ...newItems];
console.log("bucket", bucket);
if (range.start == 0) {
this.items = [...bucket.reverse(), ...this.items];
bucket = [];
}
stackblitz example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With