Cdk virtual scrolling issue
Asked Answered
A

5

15

Does any one met the issue of angular 7 cdk virtual scrolling working abnormally in mat-tab group.

https://github.com/angular/material2/issues/13981

My city component template looks like that

<cdk-virtual-scroll-viewport class="list-container" [itemSize]="50" minBufferPx="200" maxBufferPx="400" (scrolledIndexChange)="getNextBatch($event)">
  <div *cdkVirtualFor="let state of statesObservable | async; trackBy: trackByFn" class="list-group-item state-item">
    <div class="state">{{state.name}}</div>
    <div class="capital">{{state.capital}}</div>
  </div>
</cdk-virtual-scroll-viewport>

When put this city component to the mat-tab-group as the second tab

<mat-tab-group>
  <mat-tab label="Country">
    <app-country></app-country>
  </mat-tab>
  <mat-tab label="City">
    <app-city></app-city>
  </mat-tab>
</mat-tab-group>

The result looks like belenter image description hereow:

The stackblitz code is here: https://stackblitz.com/edit/angular7-virtual-scroll-issue

Does anyone have some idea for this issue?

Adventuresome answered 8/11, 2018 at 8:55 Comment(0)
B
13

You need to lazy load the tab content by declaring the body in a ng-template with the matTabContent attribute. This way, the viewport size is calculated only when the tab is shown.

  <mat-tab label="City">
    <ng-template matTabContent>
      <app-city></app-city>
    </ng-template>
  </mat-tab>

See: https://material.angular.io/components/tabs/overview#lazy-loading

Bruno answered 22/3, 2019 at 9:50 Comment(2)
This is the correct solution, all others are workarounds at best. Thanks!Skardol
Worked very well, specially with templateCacheSize: 0 on *cdkVirtualFor. Thanks!Josefina
S
10

You tell it to keep the Buffer size between 200px and 400px, yet your scroll window is much taller than that.

Change both the minimum and maximum to 1200px, this will keep the items cover your viewport, even when you scroll down for more items.

https://stackblitz.com/edit/angular7-virtual-scroll-issue-ftcnng

Sorn answered 16/1, 2019 at 14:59 Comment(4)
Changing the minimum and maximum is the workaround solution. Because the attribute name is buffer, so it should be the amount additional to the viewport size.Adventuresome
This is the right solution, for everyone that comes here. Thank you! I owe you a coffee ;)Plight
This is not the correct solution. It's a buffer that's additional to the viewportAmorita
perhaps @itsundefined, but that is not how it works/worked last time i checkedFratricide
C
5

The question has been asked some time ago, but there is a solution which is not a workaround.

First you need the Viewport Reference:

@ViewChild(CdkVirtualScrollViewport, {static: false}) cdkVirtualScrollViewport: CdkVirtualScrollViewport;

Then you can call the Method checkViewportSize() when the size of the Viewport has changed. Before you call this method you need to update the style height of the Viewport container.

this.heightChange$.subscribe(() => {
    this.cdkVirtualScrollViewport.checkViewportSize();
});
Chloras answered 19/11, 2019 at 10:41 Comment(2)
This is the correct answer. It will also update maxBufferPx & minBufferPx to work as described (additional buffer off the screen). I am using this fix on multiple projects.Druid
This is what worked for me as well. I had a situation where the virtual scroll's viewport was in a flex-box, so it needed to respond to what the flex's layout would be. When it was initialized, it was less than what it needed to be. Calling this after the view was initilaized made it take up the entire space it could.Decimeter
S
1

Works for me, thanks!

  @ViewChild(CdkVirtualScrollViewport) viewport: CdkVirtualScrollViewport;

  @HostListener('window:resize', ['$event'])
  onResize(event) {
    this.viewport.checkViewportSize();
  }
Shakitashako answered 26/11, 2019 at 16:13 Comment(2)
What to do after calling the checkViewportSize() mathod.Catheterize
Basically nothing, it's just fix the issueShakitashako
S
-1

Use ItemSize only. Avoid Max and Min Buffer.

<cdk-virtual-scroll-viewport class="list-container" [itemSize]="50" >

It needs to be the exact pixel height of a single item.

Snapback answered 7/12, 2020 at 14:19 Comment(1)
I think this is how its supposed to work. Ive seen a lot of examples where it just didn't workCentrality

© 2022 - 2024 — McMap. All rights reserved.