Angular中如何在循环内为FormControl设置值?
问题解决:Mat-Table编辑模式下输入框显示原有值
问题根源
你当前的实现存在两个核心问题:
- 所有行的输入框共用同一个
amountFieldFormControl,导致所有输入框的值同步,无法各自显示对应行的原有金额。 - 同时使用
[formControl]和[ngModel]属于错误用法,Angular不允许同时绑定表单控件和ngModel,会引发数据绑定冲突。
解决方案一:直接绑定行数据(简单场景)
这种方式适合不需要复杂表单验证、直接修改行数据的场景,无需额外的FormControl管理。
修改HTML代码
<ng-container matColumnDef="amount"> <th mat-header-cell *matHeaderCellDef>Amount <button mat-icon-button (click)="onEditClick()"> <mat-icon style="cursor: pointer;" class="ml-2 mr-2">edit</mat-icon> </button> </th> <td mat-cell *matCellDef="let row; let i=index;"> <ng-container *ngIf="isActual">{{row.amount || "-- --"}}</ng-container> <mat-form-field *ngIf="isEditMonth" class="example-full-width month-textbox" appearance="outline"> <!-- 直接双向绑定row.amount,去掉共用的formControl --> <input matInput type="text" [(ngModel)]="row.amount" (change)="onAmountChanged($event,row)" [min]="0"> </mat-form-field> </td> </ng-container>
修改TS代码
删除共用的amountField定义,其他逻辑保持不变:
// 移除这一行:amountField = new FormControl('', Validators.compose([Validators.min(0)])); onEditClick() { if (this.isEditMonth) { this.loadCharges(); this.isEditMonth = false; this.isActual = true; } else { this.isEditMonth = true; this.isActual = false; } }
解决方案二:使用FormArray管理表单(复杂场景)
如果需要对每个输入框添加验证规则、批量提交表单数据,推荐使用FormArray来管理每一行的表单控件。
修改TS代码
import { FormBuilder, FormArray, Validators } from '@angular/forms'; // 注入FormBuilder constructor(private fb: FormBuilder) {} amountFormArray: FormArray; // 在加载数据后初始化FormArray(比如在loadCharges方法中) loadCharges() { // 假设datasource是你的数据数组 this.amountFormArray = this.fb.array( this.datasource.map(row => this.fb.control(row.amount || '', Validators.min(0))) ); } onEditClick() { if (this.isEditMonth) { this.loadCharges(); this.isEditMonth = false; this.isActual = true; } else { // 进入编辑模式时确保FormArray已初始化 if (!this.amountFormArray) { this.loadCharges(); } this.isEditMonth = true; this.isActual = false; } } // 获取对应行的FormControl getAmountControl(index: number) { return this.amountFormArray.at(index) as FormControl; } // 当金额变化时同步到行数据(可选,根据需求) onAmountChanged(event: Event, row: any, index: number) { row.amount = this.getAmountControl(index).value; }
修改HTML代码
<ng-container matColumnDef="amount"> <th mat-header-cell *matHeaderCellDef>Amount <button mat-icon-button (click)="onEditClick()"> <mat-icon style="cursor: pointer;" class="ml-2 mr-2">edit</mat-icon> </button> </th> <td mat-cell *matCellDef="let row; let i=index;"> <ng-container *ngIf="isActual">{{row.amount || "-- --"}}</ng-container> <mat-form-field *ngIf="isEditMonth" class="example-full-width month-textbox" appearance="outline"> <!-- 绑定FormArray中对应索引的FormControl --> <input matInput type="text" [formControl]="getAmountControl(i)"> </mat-form-field> </td> </ng-container>
说明
- 方案一简单直接,适合快速实现编辑功能;
- 方案二更规范,适合需要表单验证、批量处理数据的场景,能更好地遵循Angular表单最佳实践。
内容的提问来源于stack exchange,提问作者Asna Khan
相关产品推荐
相关产品推荐

