components
components copied to clipboard
virtual-scroll: support items of unknown size
Support virtual scrolling over a list of items whose size is not known and needs to be measured
Been testing autosize and seems to work pretty well.
Is this released? Or are any extra steps needed? I'm getting
ERROR Error: StaticInjectorError(AppModule)[CdkVirtualScrollViewport -> InjectionToken VIRTUAL_SCROLL_STRATEGY]:
StaticInjectorError(Platform: core)[CdkVirtualScrollViewport -> InjectionToken VIRTUAL_SCROLL_STRATEGY]:
edit: looks like you need to have both
import { ScrollDispatchModule } from '@angular/cdk/scrolling';
import { ScrollingModule } from '@angular/cdk-experimental/scrolling';
imported for autosize
to work
Looking forward to see this feature! :+1:
It seems to be working fine in most of the time, except that there is always an empty space on the bottom that keeps increasing in size each time you scroll down and up a bit.
@fxck could you please share some of your code to show how to use this feature?
Just import import { ScrollingModule } from '@angular/cdk-experimental/scrolling';
and use it with autosize
directive.
<cdk-virtual-scroll-viewport [style.height.px]="height" autosize>
<div *cdkVirtualFor="let item of list">{{ item }}</div>
</cdk-virtual-scroll-viewport>
yes, it works for me :)
But if I use autosize
strategy it can not use many functions such as scrollToIndex()
...
Is there any alternative way? For example I am going to scroll to bottom
That's most likely the reason why this is experimental and not in stable. It's just not finished and feature complete yet.
I see. I have tested autosize
feature with a list of 121000 + different height items and it works well without any lag. :+1:
Is there any ETA for this feature? (but with normal functions as well :) ) This is really cool. We are going to use this for our project and really want to see this to be released!!!
any update on this feature?
@mmalerba Any updates on this? Thanks
Will this be implemented in production soon?
I've been trying to get autosize strategy to work based on fxck's example, but keep getting this error: "Can't bind to 'cdkVirtualForOf' since it isn't a known property of 'div'. " Any suggestions?
I've been trying to get autosize strategy to work based on fxck's example, but keep getting this error: "Can't bind to 'cdkVirtualForOf' since it isn't a known property of 'div'. " Any suggestions?
Try with the cdk version angular 6.0.2
any updates ? 7.0.4 angular say - Can't bind to 'cdkVirtualForOf'
angular 6.4.7 bug with autosize ( end scroll with space )
any updates ? 7.0.4 angular say - Can't bind to 'cdkVirtualForOf' angular 6.4.7 bug with autosize ( end scroll with space )
Have you tried importing both the core and experimental scroll modules? I found this alleviated the Can't bind to cdkVirtualForOf
issue.
import { ScrollingModule } from '@angular/cdk/scrolling';
import { ScrollingModule as ExperimentalScrollingModule} from '@angular/cdk-experimental/scrolling';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ScrollingModule,
ExperimentalScrollingModule,
],
bootstrap: [AppComponent]
})
export class AppModule { }
But if I use
autosize
strategy it can not use many functions such asscrollToIndex()
... Is there any alternative way? For example I am going to scroll to bottom
I am scrolling to the bottom as follows:
let top = this.viewport.measureScrollOffset("top");
let bottom = this.viewport.measureScrollOffset("bottom");
let offset = top + bottom;
this.viewport.scrollToOffset(offset);
However, there are a few layout bugs it appears - but it's to be expected since it is still an experimental feature.
Any updates on this?
any updates ? 7.0.4 angular say - Can't bind to 'cdkVirtualForOf' angular 6.4.7 bug with autosize ( end scroll with space )
Have you tried importing both the core and experimental scroll modules? I found this alleviated the
Can't bind to cdkVirtualForOf
issue.import { ScrollingModule } from '@angular/cdk/scrolling'; import { ScrollingModule as ExperimentalScrollingModule} from '@angular/cdk-experimental/scrolling'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, ScrollingModule, ExperimentalScrollingModule, ], bootstrap: [AppComponent] }) export class AppModule { }
yeah but im get error - itemSize need to be set... if im set 0, ofc scroll load all items... if set any size scroll work not like autosized (((
I have this:
"@angular/cdk": "^7.3.3",
"@angular/cdk-experimental": "7.3.3",
import { ScrollingModule } from '@angular/cdk-experimental/scrolling';
import { ScrollDispatchModule } from '@angular/cdk/scrolling';
imports: [ScrollDispatchModule, ScrollingModule],
And everything works ok with autosize.
@easyproger
What worked for me is itemSize="50"
for the cdk-virtual-scroll-viewport
and [style.height]="'auto'"
on the li
without any additional height styles applied.
I am importing both
import { ScrollingModule } from '@angular/cdk/scrolling';
import { ScrollingModule as ExperimentalScrollingModule } from '@angular/cdk-experimental/scrolling';
P.S. for some reason adding autosize
causing occasional empty space without any list items at the bottom of the viewport.
I tried to integrate mat-expansion-panels as list items. It's causing a few bugs while scrolling.
- I click on one item to open it
- I scroll down
- Suddenly other elements are open as well even if I didn't open them manually. The scrolling behaviour is not smooth anymore.
Does anybody know a workaround for this?
Any update on this? Particularly the re-introduction of the scrolledIndexChange event with variable height items. Unless anyone knows of a work-around to be able to identify when the bottom of the list has been scrolled to, so that I know to fetch more data from the back-end?
@mmalerba in Ionic the item height is optional, but when it is provided, the calculation after scrolling into a new item is skipped, resulting in a better performance:
https://github.com/ionic-team/ionic/blob/master/angular/src/directives/virtual-scroll/virtual-scroll.ts
/**
* An optional function that maps each item within their height.
* When this function is provides, heavy optimizations and fast path can be taked by
* `ion-virtual-scroll` leading to massive performance improvements.
*
* This function allows to skip all DOM reads, which can be Doing so leads
* to massive performance
*/
itemHeight?: ItemHeightFn;
Perhaps you can implement it in a similar way for Material?
I tried to integrate mat-expansion-panels as list items. It's causing a few bugs while scrolling.
- I click on one item to open it
- I scroll down
- Suddenly other elements are open as well even if I didn't open them manually. The scrolling behaviour is not smooth anymore.
Does anybody know a workaround for this?
I would expect it have something to do with how caching works - try setting templateCacheSize: 0 on the cdkVirtualFor and test it out.
Any update on this? Particularly the re-introduction of the scrolledIndexChange event with variable height items. Unless anyone knows of a work-around to be able to identify when the bottom of the list has been scrolled to, so that I know to fetch more data from the back-end?
You have found any solution or work-around? Same problem here.
Also has someone else experienced this bug ? https://angular-virtualdom-bug.stackblitz.io/ With 2 or 3 items inside the virtual scroll (depend on the height of your item) if you scroll fast to the top (once you are at the bottom) one element disappear
Any news here? This is ne of my most wanted features.
I'm going to be on vacation for most of July, but I've increased the priority as its something I'd like to work on after I get back
Will this strategy support dynamic height of the viewport too?
This is great! Are there any plans to integrate this with Material Flat Trees directly? I have documents with large tree structures (with leaves of different sizes) that I would like to display side by side. Virtual scrolling seems to work pretty well when rendering the flattened tree structure manually within the viewport. It would be awesome if I could just activate virtual scrolling with a setting in FlatTreeControl or so...
I check every day about 10 times this issue, cant wait to get this feature 👍
Hello, we are also looking forward to this feature. The experimental version is working almost correctly for us with but 2 flaws:
- When initially loading a virtual scroll with many elements, but 2 rows stretching across the entire view area, more than two rows are loaded until you scroll to the last element.
- After scrolling to the last element, it is impossible to scroll all the way back up. The view is cut off.
@mmalerba any news?
We need this feature. Still waiting for it. :smile_cat:
It seems to be working fine in most of the time, except that there is always an empty space on the bottom that keeps increasing in size each time you scroll down and up a bit.
Facing the same issue
Any update on this? Particularly the re-introduction of the scrolledIndexChange event with variable height items. Unless anyone knows of a work-around to be able to identify when the bottom of the list has been scrolled to, so that I know to fetch more data from the back-end?
Did you resolve it?
This is such a cool feature, any plans on releasing it to production yet?
This is such a cool feature, any plans on releasing it to production yet?
For that it would need to work properly, I suppose.
Cant release my image board before this feature is done ;P
As of now is there any way to have responsive list design along with virtual scroll?
I'm using Angular Flex Layout along with virtual scroll, so I believe we can be aware of what will be the size of items on any specific screen size, but can we bind itemSize property to populate it dynamically,
it won't be essentially updated once assigned apart from probably when orientation changes on Tabs or cellular devices.
someone got a good working service to calculate (without to much lost of performance) the hight of items?
Scrolling down with autosize directive is working fine but while scrolling up its jumping to the start of the list.
Anyone in the world other than me worrying about this? Is this issue a solvable or can we solve it by proving it can't be solved?
@SvenBudak @tibinthomas what I did to solve that issue instead of scrolling directly to the selected element I scroll element by it's height height to the top or bottom, check if element I look for is visible, if not scroll again until element is found. It's not perfect but it works in most situations.
@mmalerba said they would get back to this after vacation, but seems like they are working on other things now :/
Yes, supporting Ivy and creating new Test Harnesses has taken priority over this work. This is still a high priority issue that the team intends to address.
any news when this is going to be released?
cdk-virtual-scroll-viewport makes no sense to me with a fixed height.
the most important thing is that those inner items must be of fixed height
Is this thread not virtual scroll, for items of unknown size?
any update on this? My user case needs various size of rows. Using the fixed size virtual-scroll has a lot of jumping issues, but the auto-sized one is still not production ready?
It's not. I wouldn't hold my breath. This library supports varying row height with a cache: https://github.com/rintoj/ngx-virtual-scroller
in autosize, scroll down event working fine while scrolling up facing jump issue when scrolling gets to stop. any update for the same?
Here's a brute approach to a very annoying missing functionality that nobody from the angular team seems to care about.
interface RowInfo {
height: number
id: string
}
export class CustomVirtualScrollStrategy implements VirtualScrollStrategy {
private viewport:CdkVirtualScrollViewport;
private rowSizeCache = new Map<string, RowInfo>();
private orderedItemIds:string[] = [];
scrolledIndexChange = new Subject<number>();
attachedSubject = new Subject<CdkVirtualScrollViewport>();
constructor(private minItemHeight:number=48, private renderItemsBefore=2, private renderItemsAfter=2) {
}
onContentRendered(): void {
}
attach(viewport: CdkVirtualScrollViewport): void {
if(viewport == this.viewport){
return
}
this.attachedSubject.next(viewport);
this.viewport = viewport;
const changeObserver = new Observable<HTMLElement>(subscriber => {
const watchedEl = viewport.elementRef.nativeElement.firstChild as HTMLElement;
const mutationObserver = new MutationObserver(() => {
subscriber.next(watchedEl)
});
mutationObserver.observe(viewport.elementRef.nativeElement.firstChild, {
attributes: true,
//characterData: true,
childList: true,
subtree: true,
attributeOldValue: true,
//characterDataOldValue: true
});
return () => {
mutationObserver.disconnect();
}
});
changeObserver.pipe(
debounceTime(100),
takeUntil(this.attachedSubject)
).subscribe(rootEl => {
let changed = false;
// each child of cdk-virtual-scroll-viewport should have data-row-id and data-row-index attributes defined
// <div *cdkVirtualFor="let row of dataSource.onData() | async; let index = index;" [attr.data-row-id]="row.getId()" [attr.data-row-index]="index">
const list = Array.from(rootEl.querySelectorAll("[data-row-id][data-row-index]")) as HTMLElement[];
for(const el of list){
const id = el.getAttribute('data-row-id');
const idx = parseInt(el.getAttribute('data-row-index'), 10);
let rowInfo = this.rowSizeCache.get(id);
if(!rowInfo){
rowInfo = {height:0, id: id};
this.rowSizeCache.set(id, rowInfo)
}
const clientHeight = el.clientHeight;
if(rowInfo.height != clientHeight){
rowInfo.height = clientHeight;
changed = true
}
if(!isNaN(idx)){
this.orderedItemIds[idx] = id;
}
}
if(changed){
this.updateTotalContentSize();
this.updateRenderedRange()
}
})
}
private updateRenderedRange() {
if (!this.viewport) {
return;
}
// TODO handle item removal
// TODO handle reordering items
// TODO various other optimizations can be performed as we don't always need to check each row height
const scrollOffset = this.viewport.measureScrollOffset();
const viewportSize = this.viewport.getViewportSize();
const maxOffset = scrollOffset+viewportSize;
const maxLastVisibleIndex = Math.ceil(maxOffset / this.minItemHeight);
const dataLength = this.viewport.getDataLength();
let offset = 0;
const visibleRange = {startIndex:NaN, endIndex:NaN, startOffset:0, endOffset:0}; // contains rows which are partially or fully visible
for(let i=0;i < Math.min(dataLength, maxLastVisibleIndex); i++){
let itemHeight = this.minItemHeight;
const itemId = this.orderedItemIds[i];
if(itemId){
itemHeight = this.rowSizeCache.get(itemId).height
}
if(offset > maxOffset){
break;
}
if(offset+itemHeight >= scrollOffset){
if(isNaN(visibleRange.startIndex)){
visibleRange.startIndex = i;
visibleRange.startOffset = offset;
}
visibleRange.endIndex = i;
visibleRange.endOffset = offset + itemHeight;
}
offset += itemHeight;
}
const firstVisibleIndex = visibleRange.startIndex;
for(let i=this.renderItemsBefore; i>0 && visibleRange.startIndex > 0; i-=1){
visibleRange.startIndex -= 1;
visibleRange.startOffset -= this.getItemHeight(visibleRange.startIndex)
}
for(let i=this.renderItemsAfter; i>0 && visibleRange.endIndex < dataLength-1; i-=1){
visibleRange.endIndex += 1;
visibleRange.endOffset += this.getItemHeight(visibleRange.endIndex)
}
this.viewport.setRenderedRange({start:visibleRange.startIndex, end: visibleRange.endIndex+1});
this.viewport.setRenderedContentOffset(visibleRange.startOffset);
this.scrolledIndexChange.next(firstVisibleIndex);
}
private updateTotalContentSize() {
if (!this.viewport) {
return;
}
let totalHeight = 0;
for(let i=0; i< this.viewport.getDataLength(); i++){
totalHeight += this.getItemHeight(i);
}
this.viewport.setTotalContentSize(totalHeight);
}
private getItemHeight(index: number): number{
const itemId = this.orderedItemIds[index];
if(itemId){
return this.rowSizeCache.get(itemId).height
}
return this.minItemHeight;
}
detach(): void {
if(this.viewport){
this.viewport = null;
this.attachedSubject.next(null)
}
}
onContentScrolled(): void {
this.updateRenderedRange();
}
onDataLengthChanged(): void {
this.updateTotalContentSize();
this.updateRenderedRange();
}
onRenderedOffsetChanged(): void {
}
scrollToIndex(index: number, behavior: "auto" | "smooth"): void {
//TODO
}
}
Working Example
feed.component.html
<cdk-virtual-scroll-viewport
#viewport class="example-viewport"
[style.height.px]="getHeight" <!-- calc(100vh) -->
autosize fxFlex>
<div #listComponent fxFlex fxLayout="column" *ngIf="messages && messages.length > 0">
<div
*cdkVirtualFor="let item of messages;let index = index; templateCacheSize: 0;
trackBy: indexTrackFn; let i = index"
class="feed-messages" [style.height.px]="item">
<app-message *ngIf="item?.senderId"
[messageInput]="item"
[messageUser]="chatUsers.users[item.senderId]"
></app-message>
</div>
</div>
</cdk-virtual-scroll-viewport>
feed.component.ts
export class FeedComponent implements OnInit, AfterViewInit , OnDestroy {
@ViewChild(CdkVirtualScrollViewport, {static: true}) viewport: CdkVirtualScrollViewport;
@Input('isPageLoaded') set setIsPageLoaded(isPageLoaded) {
if (isPageLoaded) {
(<any>this.viewport).checkViewportSize();
console.log('isPageLoaded', isPageLoaded);
}
};
ngOnInit(): void {
fromEvent(window, 'resize')
.pipe(
distinctUntilChanged(),
debounceTime(10),
takeUntil(this.deactivatedSubject)
).subscribe(() => {
(<any>this.viewport).checkViewportSize();
});
this.viewport.elementScrolled().subscribe(() => {
console.log(this.viewport.getRenderedRange()) //{start: 4, end: 19}
})
}
}
@dudipsh Can you share online example?
I'm trying with 9.2.0 version and receiving error message:
ERROR Error: "Error: cdk-virtual-scroll-viewport requires the "itemSize" property to be set."
@arkadiusz-wieczorek
did you import the ScrollingModule from cdk-experimental?
import { ScrollingModule } from '@angular/cdk/scrolling';
import { ScrollingModule as ExperimentalScrollingModule} from '@angular/cdk-experimental/scrolling';
@NgModule({
declarations: [
],
imports: [
ScrollingModule,
ExperimentalScrollingModule,
]
})
export class FeedModule { }
thanks @dudipsh, my fault!
Looking at using an expander in virtual scroll ie a click a button and an item height expands to contain a sub-menu, which can vary per item.
Tried using the the autosize, but didn't seem to work quite right.
Is the plan for this this be able to also support this?
Autosize works but there are other features missing then. For example scrolledIndexChange is not working. But I really need to know which element is at the top.
Autosize works but there are other features missing then. For example scrolledIndexChange is not working. But I really need to know which element is at the top.
Have you tried to use the viewport to get that information?
using the this.viewport.getRenderedRange()
see the example : https://github.com/angular/components/issues/10113#issuecomment-607102447
@buenjybar
ngOnInit(): void {
this.route.paramMap.subscribe((res) => {
this.activeChannel = res.get('id');
this.chatService.readMessagesInChannel(this.activeChannel, 0, 40).subscribe((channelData: any) => {
this.messages = channelData.data.reverse().map((item, index) => {
this.scrollTo(index * 299, 'auto');
return item;
});
this.startIndex = channelData.totalCount;
});
});
this.viewport.elementScrolled()
.pipe(debounceTime(150))
.subscribe((res) => {
const {start, end} = this.viewport.getRenderedRange();
if (start === 0) {
this.fetchMore();
}
});
}
scrollTo(size, behavior: 'auto' | 'smooth' = 'auto') {
setTimeout(() => {
this.viewport.elementRef.nativeElement.scrollTo({top: size, behavior, left: 0});
}, 300);
}
Autosize works but there are other features missing then. For example scrolledIndexChange is not working. But I really need to know which element is at the top.
Have you tried to use the viewport to get that information? using the
this.viewport.getRenderedRange()
see the example : #10113 (comment)
Yes, sure with some hack you can make it work. It still would be nice if the API that the components provide would work no matter if item size is fixed or dynamic. I mean the (scrolledIndexChange) output.
@ewalddieser
I usually agree with this approach But this issue opened from 2018, it looks like it's time for "hacks"
By the way Denis Hilt works on a solution for a chat experience virtual scroll that starts from the bottom with auto height its in progress but its looks like a very good solution https://github.com/dhilt/ngx-ui-scroll
working example https://stackblitz.com/edit/ngx-ui-scroll-chat-app
When it will be released?
@dudipsh Can you share online example?
I'm trying with 9.2.0 version and receiving error message:
ERROR Error: "Error: cdk-virtual-scroll-viewport requires the "itemSize" property to be set."
@arkadiusz-wieczorek I moved to this package https://github.com/dhilt/ngx-ui-scroll no issues... work perfectly
I am looking forward to this feature too
'cdk-virtual-scroll-spacer' is not taking height beyond 22339600px, that means user can not scroll down further if list showing in virtual table is beyond 22339600px height. example: i have log viewer with millions of records, cdk-virtual-scroll-spacer height is calculated based on itemSize * numberOfItems. to show 2 millions of records with 20px row height need 40million px cdk-virtual-scroll-spacer height, but chrome is limiting cdk-virtual-scroll-spacer height to 22339600px. how do we overcome this limit ?
@vraddy this has nothing to do with this ticket. Also if you think scrolling through 2 million entries is feasible, reconsider your design choices (i.e. truncate your data).
any news about this ticket?
Any progress for this issue?
ngx-virtual-scroller lib is best for unknown size just used it till any next update. https://github.com/rintoj/ngx-virtual-scroller/
@thackerronak its not really working. the guy who created this one is not available for accepting merge requests and he also cant update the npm package. My team was testing community updates from ngx-virtual-scroller but its not working well. alot bugs and problems.
We have to wait for cdk solution. The Ionic Team wrote anything about that ion-virtual-scroll will switch to cdk. maybe ionic team is working together with the angular team on this problem. we wait already 4 years. I am not sure that this fix will come any day... i have already 4 apps they are ready to release if this cdk fix is out. i worked last 5 years on them... i just hope it will come...
Does https://github.com/rintoj/ngx-virtual-scroller/ work with tables that have sticky headers?
@Mmatiasn i used "ngx-virtual-scroller" ( for NPM package ) you can try to fork and implement sticky headers https://github.com/dudipsh/ngx-ui-table
If anyone has stumbled across the requirement for items of different, but known size (a mixture between the fixed and autosize scrolling strategies) - I've elaborated more in this SO question.
Sad to say, but the performance is much worse comparing to the fixed scrolling strategy.
dont wait for a solution. add meanwhile a intersection observer which detechts that the user reach the end of the list and load then the next X entries. This is how we did it for now. I dont think that we will get for the web a good working virtual scroll. It seems that this is a feature that works only well in native java i think.
Yeah, I'm not really waiting for it, In the end I managed to use multiple workarounds for my usecases but it just amazes me the long time this issue has been around. Btw this one works great: https://github.com/rintoj/ngx-virtual-scroller/
This package also has its problems. Just like many others. After almost 2 years we have accepted that there is simply no "perfect" solution written in JS.
Hi Angular team. Picking up from https://github.com/angular/components/issues/10113#issuecomment-778660378 (creating a strategy for scrolling items with different, but fixed sizes). I've modified the code suggested in the SO question and it seems to work. The usage is very close to the existing strategy: <cdk-virtual-scroll-viewport [itemSizes]='myDataSource.heights'>
.
- Do you think the use case is generic enough so that i try to create a PR in the experimental cdk, and eventually this becomes an official virtual scrolling strategy? If not, it can be published as a standalone npm module.
- Is there a set of tests that are meant for different scrolling strategies, something like acceptance tests that cover basic functionality? I attempted to reuse the ones for the fixed strategy, but they also include template cache/track by/etc tests.
Why all its github github youre think github is verry good?
On Mon, 14 Jun 2021, 3:55 pm Milan Milanov, @.***> wrote:
Hi Angular team. Picking up from #10113 (comment) https://github.com/angular/components/issues/10113#issuecomment-778660378 (creating a strategy for scrolling items with different, but fixed sizes). I've modified the code suggested in the SO question and it seems to work. The usage is very close to the existing strategy: <cdk-virtual-scroll-viewport [itemSizes]='worklistItemsDataSource.heights'>.
- Do you think the use case is generic enough so that i try to create a PR in the experimental cdk, and eventually this becomes an official virtual scrolling strategy? If not, it can be published as a standalone npm module.
- Is there a set of tests that are meant for different scrolling strategies, something like acceptance tests that cover basic functionality? I attempted to reuse the ones for the fixed strategy https://github.com/angular/components/blob/master/src/cdk/scrolling/virtual-scroll-viewport.spec.ts#L32, but they also include template cache/track by/etc tests.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/angular/components/issues/10113#issuecomment-860469374, or unsubscribe https://github.com/notifications/unsubscribe-auth/AS255R6GXVK44VIMALYKC33TSWYVRANCNFSM4ESGGQYQ .
@milanov the full strategy (includes viewport resize, which I decided to omit) I've adapted the SO answer from is covered with unit tests, so it's definitely possible. If you wish to create a module based on it, that'd be awesome, I would have used it instead of rolling out a custom strategy.
@milanov Rather than taking an array input like in the SO question, I think a function would be a more flexible API, e.g.:
HTML:
<cdk-virtual-scroll-viewport customVirtualScrollStrategy [itemSize]="itemSizeFn">
TS:
itemSizeFn = (item, index) => index % 2 ? 50 : 100;
I don't think we separate out the tests that are common to all scrolling strategies. I would just use the fixed size strategy tests as a template and remove ones that aren't relevant to your strategy
Thanks for the quick responses. Some followups for @mmalerba:
- I’m still not sure if I should attempt to create a PR in the experimental cdk repository, or publish the strategy separately
- (depending on the above) Would you expect the new strategy to have the same API as the current ones do (
min/maxBufferPx
). The implementation right now supports what number of elements are to be rendered before/after the visible part of the scroll (lets say 3 elements), which makes the calculations much simpler. - I don't think we can have an
itemSizeFn
with a signature of(item, index)
, as we don’t actually have access to the items in the scrolling strategy, butindex
alone would be doable
As for @Klaster1 , can you elaborate on the viewport resize part? I actually modified your code to be as close as possible to the fixed size strategy (in terms of code structure), and it seems there isn't anything missing, simply the calculations in the _updateRenderedRange
are different.
I think we can make some kind of change to this repository, I just want to make sure we settle on a good API first. That makes sense about itemSizeFn
, I figured there was a reason I didn't implement it already, and its probably because its not really possible without some big refactoring. What if for now we change the itemSize
to take number | number[]
instead of just number
. That way we don't need to add a new strategy, we could just expand the current one.
Also, I think rather than making the user enumerate all the heights, it would be nice to accept an array like [10, 100]
which would result in alternating heights of 10
and 100
for all of the items. (As opposed to what's shown in the stackblitz example you linked to, where it uses an array of 500 sizes to accomplish the same thing: Array.from(Array(500).keys()).map(i => (i % 2 ? 50 : 100))
A assume different people will have different use-cases, so lets hear opinions from the community about the API. From my perspective, @mmalerba, the way to go would be:
- Introduce a new virtual scrolling strategy with an
itemSizeFn
parameter, taking theindex
of a given element and returning its height. This new strategy will be in cdk-experimental and would render a predefined number of items before/after the currently visible viewport. - (Release and take feedback from the community)
- Add
minBufferPx
andmaxBufferPx
. This will not be a breaking change and will align this strategy with the currently existing ones. - (Release and take feedback from the community)
- (Optional) Merge the two strategies into one that takes either
itemSize
oritemSizeFn
, thus eliminating duplication of code/tests. This should be done only if the differences in the calculations can be properly isolated.
As a side note, I'm not a fan of the minBufferPx
and maxBufferPx
idea, I find it simpler to reason about the behaviour in terms of how much items should be rendered before/after the viewport. However, I assume that this API is here to stay, and therefore the suggestion above.
Could someone explain me what was wrong with jocker's brute force implementation posted earlier in this thread? Was it downvoted because of performance issues, maintainability issues, security issues, or something else?
I am asking because I also need to support a list of items of variable item size, which is very different from milanov's requirement (of different, but fixed sizes). And jocker's solution while not very elegant, gets the job done.
So far the only working solution which also supports at the end of the day the scrollToIndex
API was posted by jocker I think. So I am curious what's the main reason for the downvotes.
@milanov I only have a very subjective, but probably relevant feedback. It would be really nice if the name of the strategy would highlight the fact that the strategy is not an auto-size strategy. Just off the top of my head StaticVariableSizeScrollStrategy
or ProgrammaticVariableSizeScrollStrategy
comes to my mind as opposed to e.g. a dynamic auto size strategy.
@zergeborg Thanks for the feedback. With regards to naming, right now I'm leaning towards FixedSizesVirtualScrollStrategy
(with the s
in sizes). What I'm suggesting will not work for your case, but I'm hoping it might work for others. The three strategies (fixed size, multiple fixed sizes, dynamic size) should be complementary to each other.
It looks like autosize is included in @angular/cdk-experimental. I noticed the paragraph under the example here https://material.angular.io/cdk/scrolling/overview#scrolling-over-fixed-size-items
Is there any ETA for when cdk-experimental will be stable?
Specifically:
ERROR Error: cdk-virtual-scroll: scrolledIndexChange is currently not supported for the autosize scroll strategy
Also, elements seem to jump around a bit when adding additional entries.
"@angular/cdk": "12.2.8", "@angular/cdk-experimental": "12.2.8"
If i have set only autosize, i get an error Error: cdk-virtual-scroll-viewport requires the "itemSize" property to be set.
Is this feature ever going to be implemented?
Any update on this? Is this not being considered anymore?