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

Angular中如何在循环内为FormControl设置值?

问题解决:Mat-Table编辑模式下输入框显示原有值

问题根源

你当前的实现存在两个核心问题:

  • 所有行的输入框共用同一个amountField FormControl,导致所有输入框的值同步,无法各自显示对应行的原有金额。
  • 同时使用[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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 09:01:19