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
相关产品推荐
相关产品推荐

