0

Angular 8 brings really cool feature to implement virtual scroll. They have provide example here regarding usage of it. Although, its really difficult implement with mat-table.

I have been working on to implement virtual scroll on mat-table and found that, we need to have our own custom data source for that. I have create new data source by implementing DataSource class but what I found is that, I loose the sort and other features due to custom data source.

app.component.html

<cdk-virtual-scroll-viewport class="example-viewport">
  <table class="table" mat-table #table matSort [dataSource]="dataSource" [multiTemplateDataRows]="true">
      <ng-container matColumnDef="id">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> id </th>
          <td mat-cell *matCellDef="let element"> {{element.id}} </td>
      </ng-container>

      <ng-container matColumnDef="name">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Name</th>
          <td  mat-cell *matCellDef="let element"> {{element.name}} </td>
      </ng-container>

      <ng-container matColumnDef="age">
          <th mat-header-cell *matHeaderCellDef> Age</th>
          <td mat-cell *matCellDef="let element"> {{element.age}} </td>
      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>

      <!-- cdkVirtualScrollViewport uses transform: translateY to correct for all elements that are removed. 
      We will use a plcaholder row in the table instead because the translate causes problems with the sticky header -->
      <tr [style.height.px]="placeholderHeight" mat-row *matRowDef="let row; let index = index; columns: []; when: placeholderWhen"></tr>

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

app.component.ts

import { Component, OnInit, ViewChild, AfterViewInit } from "@angular/core";
import {
  CdkVirtualScrollViewport,
  FixedSizeVirtualScrollStrategy,
  VIRTUAL_SCROLL_STRATEGY
} from "@angular/cdk/scrolling";
import { CollectionViewer } from "@angular/cdk/collections";
import { MatSort } from "@angular/material";
// import { GridTableDataSource } from './gridTable.datasource'
import { GridTableDataSource } from "./gridTableM.datasource";

const ROW_HEIGHT = 48;
/**
 * Virtual Scroll Strategy
 */
export class CustomVirtualScrollStrategy extends FixedSizeVirtualScrollStrategy {
  constructor() {
    super(ROW_HEIGHT, 1000, 2000);
  }

  attach(viewport: CdkVirtualScrollViewport): void {
    this.onDataLengthChanged();
  }
}

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
  providers: [
    { provide: VIRTUAL_SCROLL_STRATEGY, useClass: CustomVirtualScrollStrategy }
  ]
})
export class AppComponent implements OnInit, AfterViewInit {
  placeholderHeight = 0;
  displayedColumns: string[] = ["id", "name", "age"];
  dataSource: GridTableDataSource<any>;
  rows = Array(200)
    .fill(0)
    .map((x, i) => {
      return { name: "name" + i, id: i, age: 27 };
    });
  itemSize = 48;

  @ViewChild(CdkVirtualScrollViewport, { static: true })
  viewport: CdkVirtualScrollViewport;

  @ViewChild(MatSort, { static: false }) sort: MatSort;

  constructor() {}

  ngOnInit() {
    this.dataSource = new GridTableDataSource(
      this.rows,
      this.viewport,
      this.itemSize
    );
    this.dataSource.offsetChange.subscribe(offset => {
      this.placeholderHeight = offset;
    });
    this.dataSource.data = this.rows;
    // debugger;
    // this.dataSource.sort = this.sort; // this.sort is null here
  }

  ngAfterViewInit() {
    debugger;
    this.dataSource.sort = this.sort; // this.sort is null here as well
  }

  placeholderWhen(index: number, _: any) {
    return index == 0;
  }
}

To implement sorting and other feature, I just copied code from MatTableDataSource. but somehow, this.sort is always null in any method. I couldn't find reason for this. Can anyone explain this behavior?

Here is stackblitz to play with.

Harshad Vekariya
  • 972
  • 1
  • 7
  • 28

1 Answers1

0

it doesn't work.

angular team doesn't support this https://github.com/angular/components/issues/19003

  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/29943355) – the Tin Man Sep 28 '21 at 19:09