0

Angular 8 带来了非常酷的功能来实现虚拟滚动。他们在此处提供了有关其用法的示例。虽然,它真的很难用 mat-table 实现。

我一直致力于在 mat-table 上实现虚拟滚动,发现我们需要有自己的自定义数据源。我通过实现DataSource类创建了新的数据源,但我发现,由于自定义数据源,我失去了排序和其他功能。

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;
  }
}

为了实现排序和其他功能,我只是从MatTableDataSource复制了代码。但不知何故,this.sort在任何方法中总是为空。我找不到原因。谁能解释这种行为?

这是可以玩的stackblitz 。

4

1 回答 1

0

它不起作用。

角度团队不支持这个 https://github.com/angular/components/issues/19003

于 2021-09-28T14:29:05.980 回答