cdk-virtual-scroll-viewport usage with angular/flex-layout (row and wrap)

2,691 views
Skip to first unread message

Martin Kuhn

unread,
Jan 1, 2019, 11:02:35 AM1/1/19
to Angular and AngularJS discussion
I would like to use virtual scrolling with flexlayout - e. g. the following code should work with virtual scrolling:



 
<div fxLayout="row wrap" fxLayoutAlign="start center">
     
<div *ngFor="let size of fixedSizeData; let i = index" [style.height.px]="size">
       
<div style="border: 1px dashed; padding: 6px;" [style.height.px]="size - 20">
          Item #{{i}} - ({{size}}px)
       
</div>
     
</div>
 
</div>




I made a little demo: https://stackblitz.com/edit/angular-tikbvh which shows the result (without virtualscroll) and an attempt to do the same with cdk-virtual-scroll-viewport.

Can anybody give me a hint how to do this???

Sander Elias

unread,
Jan 5, 2019, 12:18:42 AM1/5/19
to Angular and AngularJS discussion
Hi Martin,

I have been looking at your sample.
So your issue is how to add your data as rows of 5 elements to your virtual scroller? You might want to put it into chunks:

export const tail = <T>(a: Array<T>): T => a[a.length - 1];

export const chunkReducerForSize = (chunkSize = 5) => <T>(
result: T[][],
item: T
) => {
const lastElm = tail(result);
if (lastElm.length === chunkSize) {
result.push([item]);
} else {
lastElm.push(item);
}
return result;
};

export const toChunks = <T>(arr: T[], chunkSize = 5): Array<T[]> => {
return arr.reduce(chunkReducerForSize(chunkSize), [[]]);
};

(function sample() {
const fixedSizeData = Array.from(
{ length: Math.floor(Math.random() * 500) + 75 },
(e, i) => (e = Math.floor(Math.random() * 50) + 75)
);
const chunked = toChunks(fixedSizeData);
console.log(chunked);
})();

You can now iterate over the 'rows' for the virtual scroller, and inside the 'row', you iterate over the items.

Hope this helps you a bit,
Regards
Sander

Martin Kuhn

unread,
Jan 7, 2019, 12:48:58 AM1/7/19
to Angular and AngularJS discussion
Hi Sander,

thanks for answering. But I can not imagine how this can solve my problem...  I would also like to use the responsive features of flexlayout and so on...

BTW, I am curious but what is the benefit of material virtual scrolling capabilities when none of the material components can be used with it (table, list, flexlayout etc.)

Regards,

Martin

Sander Elias

unread,
Jan 7, 2019, 5:38:33 AM1/7/19
to Angular and AngularJS discussion
Hi Martin,

Oh they do work with the cdk virtual scroll (CVS from here on). However, your example has multiple items on a single "row". There is no way CVS is able to determine how much space is needed. You iterate over say 100 items, this results in 20 rows of 5 elements. How do you expect that CVS does that calculation? To make it more complex, CVS needs to know which elements are in view. 
You can use the responsive features, but not without some scripting. Use it to determine how many elements you can fit in a row, then use my helper to make chunks that fit the rows, then you can use CVS to show the result.

Regards
Sander

Martin Kuhn

unread,
Jan 7, 2019, 7:04:18 AM1/7/19
to Angular and AngularJS discussion
Hi Sander,

o.k. now I get it... Thx for help

Regards,
Martin
Reply all
Reply to author
Forward
0 new messages