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

Angular ngFor动态添加对象时输入框值重置问题

我看了你的问题,这是Angular中*ngFor和双向绑定常见的小问题,主要是表单控件的唯一标识和绑定冲突导致的,咱们一步步来解决:

问题根源分析

  1. name属性错误:你的输入框name用了{{index}},但在*ngFor里定义的索引变量是k,这个index是未定义的,导致所有输入框的name重复或无效,Angular无法正确关联每个输入框和对应的模型值,列表更新时就会重置输入内容。
  2. 重复绑定冲突:你同时使用了[(ngModel)]和value属性——[(ngModel)]已经是双向绑定了,手动设置value会和ngModel的绑定逻辑冲突,引发渲染异常。
  3. 缺少trackBy优化:*ngFor默认按对象引用追踪列表项,添加新对象时,Angular可能会重新渲染整个列表,而不是只添加新项,这也会导致已有输入框的值被重置。

修正方案

第一步:修正模板代码

去掉多余的value属性,修正name的索引变量,加上trackBy优化:

<div *ngFor="let colorSet of quantity.colorSets; let k=index; trackBy: trackByColorSetIndex;">
  <div>
    <label>Color Sets:</label>
    <div>
      <mat-form-field>
        <input matInput [(ngModel)]="quantity.colorSets[k].setQ" name="colorSetQ-{{k}}" type="text">
      </mat-form-field>
    </div>
  </div>
  <div>
    <label>Price:</label>
    <div>
      <mat-form-field>
        <input matInput [(ngModel)]="quantity.colorSets[k].price" name="colorSetPrice-{{k}}" type="text">
      </mat-form-field>
    </div>
  </div>
</div>

第二步:在组件中添加trackBy函数

在组件类里新增一个trackBy函数,帮助Angular高效追踪列表项:

model: any = { TenantId: '', CustomFieldName: '', quantities: [] };
newQuantity = { price: '', rangestart: '', rangeend: '', colorSets: [] };
colorSetInfo = { setQ: '', price: '' }

// 新增trackBy函数,用索引追踪列表项
trackByColorSetIndex(index: number, item: any): number {
  return index;
}

addNewPriceSet(quantitySet) {
  if (quantitySet) {
    quantitySet.colorSets.push({ setQ: '', price: '' });
    console.log(quantitySet);
    console.log(this.model);
  }
}

修改生效的原因

  • 唯一的name属性:每个输入框现在有唯一的标识(比如colorSetQ-0、colorSetQ-1),Angular可以正确关联输入控件和模型属性,不会在列表更新时混淆控件。
  • 移除重复绑定:只保留[(ngModel)],让双向绑定正常工作,避免了value和ngModel的逻辑冲突。
  • trackBy优化:告诉Angular用索引追踪列表项,添加新的colorSet时,只会渲染新的项,不会重新渲染已有的输入框,已输入的值就不会被重置了。

你可以试试这个修改,应该就能解决输入框重置的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:37:44