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

Angular表单添加数组元素时丢失已填数据问题求助

问题描述

点击「aggiungi gruppo」按钮会向*ngFor指令循环遍历的数组中添加元素,但将所有HTML内容用<form>标签包裹后,每次添加新元素,之前填写的表单值都会丢失;不使用<form>标签则一切正常。

HTML代码

<h1>Gestione esercizi</h1>
<!-- <form #EsercizioForm="ngForm" style="display: flex;flex-direction: column;" (submit)="OnSubmit(EsercizioForm)"> -->
<mat-form-field >
  <mat-label>Nome esercizio</mat-label>
  <input matInput placeholder="Squat" required name="nomeEsercizio" ngModel>
</mat-form-field>
<mat-form-field class="example-full-width">
  <mat-label>Descrizione</mat-label>
  <textarea matInput placeholder="Es. accosciata" name="descrizioneEsercizio" ngModel></textarea>
</mat-form-field>
<div style="display: flex;flex-direction: column;">
  <mat-form-field *ngFor="let cg of elencoGruppiMuscolari;let i = index;">
     <mat-select placeholder="gruppo muscolare" name="nome" [(ngModel)]="elencoGruppiMuscolari[i].nome"  >
      <mat-option *ngFor="let g of gruppiMuscolari" [value]="g.nome">
         {{g.nome}}
      </mat-option>
    </mat-select>
  </mat-form-field>
</div>
<div><span>Aggiungi un gruppo</span><button type="button" mat-icon-button (click)="OnAddClasseGruppoMuscolare()">
  <mat-icon>add</mat-icon>
</button></div>
<button mat-button color="primary" type="button" (click)="OnSubmit(null)">Crea</button>
<!-- </form> -->   

TypeScript代码

import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Esercizio } from 'src/app/modelli/esercizio';
import { gruppoMuscolare } from 'src/app/modelli/gruppoMuscolare';

@Component({
  selector: 'app-esercizio',
  templateUrl: './esercizio.component.html',
  styleUrls: ['./esercizio.component.css']
})
export class EsercizioComponent implements OnInit{

  private esercizio:Esercizio
  //  esercizio.gruppiMuscolari =gruppoMuscolare[];
  // esercizio.elencoGruppiMuscolari : gruppoMuscolare[]
  elencoGruppiMuscolari = [{nome:''}];

  gruppiMuscolari = [
    {nome:'bicipiti'},
    {nome:'tricipiti'},
    {nome:'petto'},
    {nome:'dorsali'},
    {nome:'trapezio'},
    {nome:'deltoide'},
    {nome:'quadricipiti'},
    {nome:'ischiodurali'},
    {nome:'polpacci'},
    {nome:'lombari'},
    {nome:'glutei'},
  ];
  ngOnInit(): void {

  }
  constructor(){}

  OnAddClasseGruppoMuscolare()
  {
    //here's where i add the new element
    this.elencoGruppiMuscolari.push({nome:''});
    // 
  }
  OnSubmit(ngForm:NgForm)
  {
    this.esercizio.nome= ngForm.value.nome;
    this.esercizio.descrizione= ngForm.value.descrizione;
    this.esercizio.gruppiMuscolari=this.elencoGruppiMuscolari;
  }
}
解决方案

问题核心是模板驱动表单中动态生成的控件name属性重复,Angular会基于name属性注册表单控件,重复的name会导致表单状态混乱,添加新元素触发DOM重渲染时丢失输入值。

具体修复步骤:

  • 给动态控件设置唯一name属性
    给mat-select的name加上索引后缀,确保每个控件在表单中唯一:

    <mat-select placeholder="gruppo muscolare" name="gruppoMuscolare-{{i}}" [(ngModel)]="cg.nome">
    
  • 简化ngModel绑定
    直接绑定到*ngFor循环的cg变量,无需通过数组索引,避免索引追踪问题:

    <mat-form-field *ngFor="let cg of elencoGruppiMuscolari;let i = index;">
      <mat-select placeholder="gruppo muscolare" name="gruppoMuscolare-{{i}}" [(ngModel)]="cg.nome">
        <mat-option *ngFor="let g of gruppiMuscolari" [value]="g.nome">
          {{g.nome}}
        </mat-option>
      </mat-select>
    </mat-form-field>
    
  • 初始化esercizio对象
    原代码中esercizio未初始化,提交时会报错,需在ngOnInit中初始化:

    ngOnInit(): void {
      this.esercizio = new Esercizio(); // 假设Esercizio类有默认构造函数
    }
    
  • 修正表单提交逻辑
    匹配表单字段的真实name值,避免取值错误:

    OnSubmit(ngForm:NgForm)
    {
      this.esercizio.nome= ngForm.value.nomeEsercizio;
      this.esercizio.descrizione= ngForm.value.descrizioneEsercizio;
      this.esercizio.gruppiMuscolari=this.elencoGruppiMuscolari;
    }
    

完成以上修改后,重新启用<form>标签,添加新元素时就不会丢失之前的表单值了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 21:07:29