Angular 需要在mat表中的每一新行上重新分配数据、分页器和排序

Angular 需要在mat表中的每一新行上重新分配数据、分页器和排序,angular,typescript,angular-material,mat-table,Angular,Typescript,Angular Material,Mat Table,我得到了一个,其中我实现了一个addRow()函数,该函数使用一组基于数据类型的默认值在表中创建新行 我遇到的问题是,每次创建新行时,我都需要重新分配MatTableDataSource、MatPaginator和MatSort。如果我不执行重新分配,则新数据不会显示,或者分页/排序不起作用 所有这些重新分配似乎都很昂贵和迂回,特别是在更大的数据集上,但我不完全确定如何做得更好 动态表.component.ts import { Component, OnInit, ViewChild } fr

我得到了一个
,其中我实现了一个
addRow()
函数,该函数使用一组基于数据类型的默认值在表中创建新行

我遇到的问题是,每次创建新行时,我都需要重新分配
MatTableDataSource
MatPaginator
MatSort
。如果我不执行重新分配,则新数据不会显示,或者分页/排序不起作用

所有这些重新分配似乎都很昂贵和迂回,特别是在更大的数据集上,但我不完全确定如何做得更好

动态表.component.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { TableField } from 'src/app/models/table-field';

const fields: TableField[] = [
  { name: "job", type: "string", editType: "free", options: [] },
  { name: "wage", type: "string", editType: "free", options: [] },
  { name: "state", type: "string", editType: "spinner", options: ["MI", "CA", "TX"] },
  { name: "isUnion", type: "boolean", editType: "checkbox", options: [] }
];

const rows: any[] = [
  { job: "J1", wage: "10.00", state: "MI", isUnion: false },
  { job: "J2", wage: "15.00", state: "TX", isUnion: true },
  { job: "J3", wage: "77.00", state: "CA", isUnion: true }
];

@Component({
  selector: 'app-dynamic-table',
  templateUrl: './dynamic-table.component.html',
  styleUrls: ['./dynamic-table.component.css']
})
export class DynamicTableComponent implements OnInit {
  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
  @ViewChild(MatSort, { static: true }) sort: MatSort;

  Fields: {}[];
  Rows: {}[];
  ColumnHeaders: string[];
  dataSource: MatTableDataSource<{}>;
  constructor() { }

  ngOnInit() {
    this.Fields = fields.map(field => field);
    this.ColumnHeaders = this.Fields.map(field => field["name"]);
    this.Rows = rows.map(row => row);
    console.log(this.Fields);
    console.log(this.Rows);
    console.log(this.ColumnHeaders);
    this.dataSource = new MatTableDataSource(rows);
  }

  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  addRow() {
    let row = {};
    fields.forEach(field => {
      switch(field.editType) { 
        case "free": { 
           row[field.name] = "default"
           break; 
        } 
        case "spinner": { 
           row[field.name] = field.options[0]; 
           break; 
        }
        case "checkbox": { 
          row[field.name] = false;
          break; 
       }
      } 
    });
    this.Rows = this.Rows.concat(row);
    this.dataSource = new MatTableDataSource(this.Rows);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  printRows() {
    console.log(this.dataSource.data)
  }
}
从'@angular/core'导入{Component,OnInit,ViewChild};
从'@angular/material/paginator'导入{MatPaginator};
从'@angular/material/sort'导入{MatSort};
从“@angular/material/table”导入{MatTableDataSource};
从'src/app/models/table field'导入{TableField};
常量字段:TableField[]=[
{名称:“作业”,类型:“字符串”,编辑类型:“自由”,选项:[]},
{名称:“工资”,类型:“字符串”,编辑类型:“自由”,选项:[]},
{name:“state”,type:“string”,editType:“微调器”,选项:[“MI”,“CA”,“TX”]},
{name:“isUnion”,type:“boolean”,editType:“checkbox”,选项:[]}
];
常量行:任意[]=[
{职务:“J1”,工资:“10.00”,状态:“MI”,isUnion:false},
{工作:“J2”,工资:“15.00”,州:“TX”,isUnion:true},
{工作:“J3”,工资:“77.00”,州:“CA”,isUnion:true}
];
@组成部分({
选择器:“应用程序动态表”,
templateUrl:'./dynamic table.component.html',
样式URL:['./动态表.component.css']
})
导出类DynamicTableComponent实现OnInit{
@ViewChild(MatPaginator,{static:true})paginator:MatPaginator;
@ViewChild(MatSort,{static:true})sort:MatSort;
字段:{}[];
行:{}[];
列标题:字符串[];
数据源:MatTableDataSource;
构造函数(){}
恩戈尼尼特(){
this.Fields=Fields.map(field=>field);
this.ColumnHeaders=this.Fields.map(field=>field[“name”]);
this.Rows=Rows.map(row=>row);
console.log(this.Fields);
console.log(this.Rows);
console.log(this.ColumnHeaders);
this.dataSource=新MatTableDataSource(行);
}
ngAfterViewInit(){
this.dataSource.paginator=this.paginator;
this.dataSource.sort=this.sort;
}
addRow(){
设row={};
fields.forEach(字段=>{
开关(field.editType){
案例“自由”:{
行[field.name]=“默认”
打破
} 
案例“微调器”:{
行[field.name]=field.options[0];
打破
}
案例“复选框”:{
行[field.name]=false;
打破
}
} 
});
this.Rows=this.Rows.concat(row);
this.dataSource=新MatTableDataSource(this.Rows);
this.dataSource.paginator=this.paginator;
this.dataSource.sort=this.sort;
}
printRows(){
log(this.dataSource.data)
}
}
动态表.component.html

<table mat-table [dataSource]="dataSource" matSort>
    <ng-container *ngFor="let field of Fields" matColumnDef="{{field.name}}">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>{{field.name}}</th>
        <td mat-cell *matCellDef="let row">
            <input *ngIf="field.editType == 'free'" matInput [(ngModel)]="row[field.name]" placeholder="{{row[field.name]}}" required>
            <mat-select *ngIf="field.editType == 'spinner'" [(ngModel)]="row[field.name]">
                <mat-option *ngFor="let option of field.options" [value]="option">{{option}}</mat-option>
            </mat-select>
            <mat-checkbox *ngIf="field.editType == 'checkbox'" [(ngModel)]="row[field.name]">
            </mat-checkbox>
        </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="ColumnHeaders"></tr>x
    <tr mat-row *matRowDef="let row; columns: ColumnHeaders;"></tr>
</table>

<mat-paginator #paginator [pageSizeOptions]="[10, 20, 30]" showFirstLastButtons></mat-paginator>
<button mat-button color="primary" (click)="addRow()">Add Row</button>
<button mat-button color="primary" (click)="printRows()">Print Rows</button>

{{field.name}
{{option}}
x
添加行
打印行

您可以使用setter对组件进行分页和排序

@ViewChild(MatPaginator, { static: false })
  set paginator(value: MatPaginator) {
    if(this.dataSource) {
      this.dataSource.paginator = value;
    }
  }
  @ViewChild(MatSort, { static: false }) 
  set sort(value: MatSort) {
    if(this.dataSource) {
      this.dataSource.sort = value;
    }
  }
您可以在此处删除分配:

  ngAfterViewInit() {
    //this.dataSource.paginator = this.paginator;
    //this.dataSource.sort = this.sort;
  }
要修改表,您别无选择,只能重新分配数据源。 添加新行时,只需修改数据源即可。由于设置器,分页器和排序组件将更新

  addRow() {
    let row = {};
    fields.forEach(field => {
      switch(field.editType) { 
        case "free": { 
           row[field.name] = "default"
           break; 
        } 
        case "spinner": { 
           row[field.name] = field.options[0]; 
           break; 
        }
        case "checkbox": { 
          row[field.name] = false;
          break; 
       }
      } 
    });
    this.Rows = this.Rows.concat(row);
    this.dataSource.data = this.Rows;
  }

作为TS/JS的新手,是否通过引用将分配给MatTableDataSource?我预计一旦我们上线,这个表将容纳数千行,因此重新分配每一新行上的所有数据听起来像是一个潜在的问题。您可以使用15000个条目进行测试,例如,您不会有任何性能问题。角度材料的官方文档中描述了静态数据源的重新分配。但是,如果您使用外部数据源,我建议您使用MatDataSource的connect()方法,这里的概述对此进行了解释:感谢您提供了额外的链接。静态数据仅用于POC,我将更新以从实时/外部源提取。