Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Virtual Scroll in Angular Material 2 Table with @angular/cdk-experimental

Tags:

I have a table displays so many rows, I want to optimize the performance of it. I've found a solution by using Virtual Scroll technique. Here is an example of Angular Material CDK Vritual Scroll Viewport Component with a simple div I've found:

<cdk-virtual-scroll-viewport class="list-container lg" [itemSize]="52.5">   <div *cdkVirtualFor="let state of statesObservable | async;" class="list-group-item">      <div class="state">{{state.name}}</div>      <div class="capital">{{state.capital}}</div>   </div> </cdk-virtual-scroll-viewport> 

However, I want to integrate it with Angular Material Table like below

<table mat-table [dataSource]="dataSource">     <ng-container  *ngFor="let c of displayedColumns" [matColumnDef]="c">       <th mat-header-cell *matHeaderCellDef>{{getTitle(c)}}</th>       <td mat-cell style="white-space: pre-wrap;" *matCellDef="let element"> {{element[c]}}</td>     </ng-container>     <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>     <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>  </table> 

I was wondering how to wrap that cdk-virtual-scroll-viewport to mat-table. My table displays up to 1000 rows and more than 20 columns, and the performance is pretty slow while it's loading and scrolling.

PS: I know that it can be solved by using Paginator, but I don't want to do that.

Versions

  1. "@angular/material": "^6.2.0"
  2. @angular/cdk": "^6.2.0"
  3. @angular/cdk-experimental": "^6.2.1"
  4. "@angular/core": "6.0.3"
  5. "@angular/cli": "6.0.7"
like image 321
Seanghay Avatar asked Jun 05 '18 02:06

Seanghay


People also ask

How do I use CDK virtual scroll?

We need to add the tag, <cdk-virtual-scroll-viewport></cdk-virtual-scroll-viewport> to work with virtual scroll module. The tag needs to be added to . html file where we want the data to be displayed. Here is the working of <cdk-virtual-scroll-viewport> in app.

What is itemSize in CDK virtual scroll viewport?

[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.

What is cdkVirtualFor?

*cdkVirtualFor accepts data from an Array , Observable<Array> , or DataSource . The DataSource for the virtual scroll is the same one used by the table and tree components. A DataSource is simply an abstract class that has two methods: connect and disconnect .


2 Answers

This is not something that currently exists out of the box. The CdkTable (or MatTable) component does not support virtual scroll YET.

The virtual scroll support baked into @angular/cdk is still in it's experimental phase - this will change in version 7.

However, when this feature lands the next step will be to implement it for the table. I will explain why.

cdk-virtual-scroll-viewport is a container for the *cdkVirtualFor directive, if we look into this directive (CdkVirtualForOf) we can see that

  1. It implements CollectionViewer (code)

  2. It accepts (works with) DataSource instance (code)

With this in mind, let's look at the CdkTable

  1. It implements CollectionViewer (code)

  2. It accepts (works with) DataSource instance (code)

The similarity is not by chance, the table (with some adjustments) can be used by cdk-virtual-scroll-viewport like the cdkVirtualFor is used.

I'm not sure what the final implementation will be, whether the developer will be able to wrap the table from the outside or the table will set it internally but this is the direction it will be.

If I had to guess I would say that the dev will choose if he wants to wrap the table with a virtual scroll. This is because cdk-virtual-scroll-viewport does not query for cdkVirtualFor (via ViewChild), it is passive and waits for something to attach it. Which is a sign that this was thought of pre-hand.

You can do it right now, by extending CdkTable and making the adjustments yourself, this will require an understanding of the table internals and might take some time. I suggest waiting a bit.

like image 68
Shlomi Assaf Avatar answered Oct 17 '22 16:10

Shlomi Assaf


I made a custom directive, what can solve this problem:

1) install a package: $ npm install -save ng-table-virtual-scroll and add it to imports:

import { TableVirtualScrollModule } from 'ng-table-virtual-scroll';  @NgModule({   imports: [     // ...     TableVirtualScrollModule   ] }) export class AppModule { } 

2) use the custom DataSource from the package:

import { TableVirtualScrollDataSource } from 'ng-table-virtual-scroll';  @Component({...}) export class MyComponent {    dataSource = new TableVirtualScrollDataSource();  } 

3) use the directive on viewport container:

<cdk-virtual-scroll-viewport tvsItemSize style="height: 400px;">     <table mat-table [dataSource]="dataSource">     ...     </table> </cdk-virtual-scroll-viewport> 

The directive allows you to use all features of mat-table, such as sort, pagination, sticky header/column, etc

like image 24
Diprokon Avatar answered Oct 17 '22 16:10

Diprokon