简体   繁体   中英

Proper use of Virtual Scrolling with Angular Material and mat-tables?

Alright, so recently I've been trying to migrate some of my table functionality over to using virtual scrolling, simply because the DOM is being bogged down with hundreds of nodes all at once with large data sets.

That being said, I was just going to use the Angular Material CDK virtual table scrolling directive on my tables, since they are mat-tables anyways. I found some examples and all, though I can't seem to get things to properly work.

These are the sources I was using for info:

Below is the template I'm using here for the table

<cdk-virtual-scroll-viewport tvsItemSize>
  <table mat-table *ngIf="yuleLogs.length > 0" [dataSource]="yuleLogs">

    <!-- logID Column -->
    <ng-container matColumnDef="logID">
      <th mat-header-cell class="logIDHeader" *matHeaderCellDef> Log ID </th>
      <td mat-cell *matCellDef="let yuleLog">{{ yuleLog.logID }}</td>
    </ng-container>

    <!-- logCategory Column -->
    <ng-container matColumnDef="logCategory">
      <th mat-header-cell class="logCategoryHeader" *matHeaderCellDef> Log Category </th>
      <td mat-cell *matCellDef="let yuleLog">{{ yuleLog.category.categoryName }}</td>
    </ng-container>

    <!-- logText Column -->
    <ng-container matColumnDef="logText">
      <th mat-header-cell class="logTextHeader" *matHeaderCellDef> Log Information </th>
      <td mat-cell *matCellDef="let yuleLog">{{ yuleLog.logText }}</td>
    </ng-container>

    <!-- logDate Column -->
    <ng-container matColumnDef="logDate">
      <th mat-header-cell class="logDateHeader" *matHeaderCellDef> Log Date </th>
      <td mat-cell *matCellDef="let yuleLog">{{yuleLog.logDate.toLocaleDateString()}} {{ yuleLog.logDate.toLocaleTimeString() }} (Eastern Standard Time)</td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="columns"></tr>
    <tr mat-row *matRowDef="let row; columns: columns;"></tr>
  </table>
</cdk-virtual-scroll-viewport>

And the actual Typescript

import { Component, Input, OnInit } from '@angular/core';
import { YuleLog } from 'src/classes/yuleLogTypes';

@Component({
  selector: 'app-log-table',
  templateUrl: './log-table.component.html',
  styleUrls: ['./log-table.component.css']
})
export class LogTableComponent implements OnInit {

  constructor() { }

  @Input() yuleLogs: Array<YuleLog> = [];

  columns: string[] = ["logID", "logCategory", "logText", "logDate"];

  ngOnInit(): void {
  }

}

So I'm aware that the data source for the table needs to be a TableVirtualScrollDataSource object and all, though the problem here is that this is a child table that should be variable and usually is based on the data in the input. Many of the Angular Material examples make constants outside of the class, which wouldn't exactly help out in the realm of using Input binding and all, so my question is, what is the best way in this situation to make the @Input() array as it is, but pass its data to a TableVirtualScrollDataSource variable, keeping in mind that the actual array might change because of the parent?

You could set the DataSource everytime the @Input changes, either via setter/getter, like this:

public dataSource: TableVirtualScrollDataSource<YuleLog> = new TableVirtualScrollDataSource([]);

@Input()
public get yuleLogs(): Array<YuleLog> {
    return this.dataSource.data;
}
public set yuleLogs(value: Array<YuleLog>) {
    this.dataSource = new TableVirtualScrollDataSource(value);
};

Or you can use ngOnChanges

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM