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

Angular表单多输入项数据重复问题求助

Angular动态表单多输入项数据重复问题解决

问题根源

  1. 所有动态生成的输入项都绑定到同一个FormGroup(addInvoiceForm)的name/count/price控件,导致所有输入框共享同一数据源,输入时互相覆盖,提交时只能获取到最后一次输入的值。
  2. addData方法遍历items时,始终取this.addInvoiceF['name'].value这类全局控件的值,而非每个动态项自己的表单数据,最终所有项数据完全重复。

解决方案:使用FormArray管理动态表单组

Angular的FormArray是专门用来管理一系列动态表单控件/表单组的工具,能让每个输入项拥有独立的数据源,彻底解决数据重复问题。

1. 修改TypeScript代码

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators, FormBuilder, FormArray } from '@angular/forms';
import { PagesService } from '../pages.service';
import { Router } from '@angular/router';

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

  addInvoiceForm!: FormGroup;
  // 获取表单数组
  get itemsFormArray(): FormArray {
    return this.addInvoiceForm.get('items') as FormArray;
  }

  constructor(
    private formBuilder: FormBuilder,
    private pagesService: PagesService,
    private router: Router
  ) {
    window.addEventListener('beforeunload', () => {
      for (let key in localStorage) {
        if (key.includes('formRows')) {
          localStorage.removeItem(key);
        }
      }
    });
  }

  ngOnInit(): void {
    // 初始化表单,包含一个FormArray,默认有一个表单组
    this.addInvoiceForm = this.formBuilder.group({
      items: this.formBuilder.array([this.createItemFormGroup()])
    });
  }

  // 创建单个项的表单组
  private createItemFormGroup(): FormGroup {
    return this.formBuilder.group({
      name: ['', Validators.required],
      count: ['', Validators.required],
      price: ['', Validators.required]
    });
  }

  // 添加新的表单项
  addForm() {
    this.itemsFormArray.push(this.createItemFormGroup());
  }

  // 删除指定表单项
  deleteForm(index: number) {
    if (this.itemsFormArray.length > 1) { // 至少保留一个项
      this.itemsFormArray.removeAt(index);
    }
  }

  addData() {
    if (this.addInvoiceForm.invalid) {
      return;
    }

    // 直接获取FormArray的所有值,无需手动映射
    const formRows = this.itemsFormArray.value;
    
    this.pagesService.setFormData(formRows);
    console.log(formRows);
    this.router.navigate(['/preview-invoice']);
  }
}

2. 修改HTML模板

<form method="POST" [formGroup]="addInvoiceForm" (ngSubmit)="addData()">
  <!-- 绑定FormArray -->
  <div class="formularz" *ngFor="let item of itemsFormArray.controls; let i = index" [formGroupName]="i">
    <mat-form-field>
      <mat-label>Name</mat-label>
      <input type="text" matInput formControlName="name" maxlength="30" minlength="3" required>
      <mat-error *ngIf="itemsFormArray.controls[i].get('name')?.errors?.['required']">Name is required</mat-error>
    </mat-form-field>
    <mat-form-field>
      <mat-label>Count</mat-label>
      <input type="number" formControlName="count" matInput>
    </mat-form-field>
    <mat-form-field>
      <mat-label>Price</mat-label>
      <input type="number" matInput formControlName="price" required>
      <mat-error *ngIf="itemsFormArray.controls[i].get('price')?.errors?.['required']">Price is required</mat-error>
    </mat-form-field>
    <button mat-icon-button color="primary" class="delete" matTooltip="Remove item" (click)="deleteForm(i)">
      <mat-icon>delete</mat-icon>
    </button>
  </div>
  <div class="add-new">
    <button type="button" mat-icon-button color="primary" class="add" matTooltip="Add new item" (click)="addForm()">
      <mat-icon>add</mat-icon>
      Add new item
    </button>
  </div>
  <div class="add">
    <button mat-icon-button color="primary" class="myButton" id="add_data_button">
      Submit
    </button>
  </div>
</form>

关键改动说明

  • 用FormArray替代原来的items数组,每个动态项都是FormArray中的一个独立FormGroup,数据互不干扰。
  • HTML中通过formArrayName绑定数组,formGroupName绑定数组索引,确保每个输入框对应正确的表单控件。
  • 表单验证改为针对当前索引的控件,避免全局控件的混淆。
  • addData方法直接获取FormArray的value,无需手动映射,数据准确且代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:57:02