You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Mat table点击添加行时复制全部条目而非新增单行问题排查

问题修复方案

核心问题原因

  • 模板内多余循环:MatTable 本身会通过 [dataSource] 自动遍历所有行数据,你在每个单元格内部额外加了 *ngFor="let ed of educationType",相当于每一行都重复渲染所有已有教育数据,导致新增一行时视觉上出现条目翻倍的效果
  • 数据源不同步:你从接口拉取的用户已有教育数据存在 educationType 变量中,没有同步给表格绑定的 educationdataSource,迫不得已在模板中额外循环 educationType 才导致错乱
  • 冗余代码干扰:表格末尾额外加了 <tr *ngFor="let field of edfieldArray; let i = index"> 无用行,同时接口请求重复调用了两次 getEducation(id) 属于冗余逻辑

修复步骤

1. 修正TS逻辑

优先使用官方推荐的 MatTableDataSource 管理数据源,无需手动调用 renderRows 触发渲染:

import { MatTableDataSource } from '@angular/material/table';

@ViewChild('educationTable') table: MatTable<any>;
educationdisplayedColumns: string [] = ['education', 'educationkind', 'deleteButton'];
// 初始化符合Ausbildung接口规范的数据源
educationdataSource = new MatTableDataSource<Ausbildung>([]);
educationDataLoaded = false;
allEducationTypes = [];
allEducationsTitleType = [];

// 新增行逻辑
addEducation() {
  const newRow: Ausbildung = {bezeichnung: '', abschluss: ''};
  // 解构赋值触发数据源变更检测
  this.educationdataSource.data = [...this.educationdataSource.data, newRow];
}

// 按索引删除指定行,避免永远删除最后一行的问题
deleteEducation(index: number) {
  const data = this.educationdataSource.data;
  data.splice(index, 1);
  this.educationdataSource.data = [...data];
}

// 接口请求逻辑合并重复请求
this.route.params.subscribe(params => {
  const id = params['id'];
  this.aService.getEducation(id).subscribe(data => { 
    // 把拉取到的已有数据直接赋值给表格数据源
    this.educationdataSource.data = data;
    this.educationDataLoaded = true;
  })
})
// 获取第一列通用选项
this.aService.getAllEducations().subscribe(data => { 
  this.allEducationTypes = data;  
})
// 获取第二列通用选项
this.aService.getEducationTitles().subscribe(data => { 
  this.allEducationsTitleType = data; 
})

2. 修正模板代码

删除单元格内多余循环、无用行,调整下拉框绑定逻辑为当前行数据:

<div id="education">
  <h4> Ausbildungen </h4>
  <mat-divider> </mat-divider>
  <table #educationTable mat-table [dataSource]="educationdataSource">
    
    <ng-container matColumnDef="education">
      <th mat-header-cell *matHeaderCellDef>Art.</th>
      <td mat-cell *matCellDef="let element">
        <ng-container *ngIf="educationDataLoaded">
          <mat-form-field>
            <!-- 绑定当前行的对应属性,支持双向绑定实时同步数据 -->
            <mat-select [(value)]="element.bezeichnung">
              <mat-option *ngFor="let education of allEducationTypes" [value]="education.bezeichnung">
                {{education.bezeichnung}}
              </mat-option>
            </mat-select>
          </mat-form-field>
        </ng-container>
      </td>
    </ng-container>
  
    <ng-container matColumnDef="educationkind">
      <th mat-header-cell *matHeaderCellDef>Abschluss</th>
      <td mat-cell *matCellDef="let element">
        <ng-container *ngIf="educationDataLoaded">
          <mat-form-field>
            <mat-select [(value)]="element.abschluss">
              <mat-option *ngFor="let educationTitle of allEducationsTitleType" [value]="educationTitle.bezeichnung">
                {{educationTitle.bezeichnung}}
              </mat-option>
            </mat-select>
          </mat-form-field>
        </ng-container>
      </td>
    </ng-container>
  
    <ng-container matColumnDef="deleteButton">
      <th mat-header-cell *matHeaderCellDef>Löschen</th>
      <td mat-cell *matCellDef="let element; let i = index">
        <!-- 传入当前行索引实现指定行删除 -->
        <mat-icon color="warn" (click)="deleteEducation(i)"> delete </mat-icon> 
      </td>
    </ng-container>
  
    <tr mat-header-row *matHeaderRowDef="educationdisplayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: educationdisplayedColumns; "></tr>
  </table>
  <button mat-raised-button color="primary" (click)="addEducation()">Neu</button>
</div>

内容的提问来源于stack exchange,提问作者Chopper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:57:02