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

Angular 5:如何获取表格动态增删行的输入值及总价

嘿,我看你现在的问题出在**所有行都用了相同的formControlName**上——Angular里每个表单控件的名字是唯一的,所以你新增的行其实都绑定到同一个值,自然没法单独获取每一行的输入。得换成FormArray来处理这种动态行的场景,这才是Angular表单设计里用来管理动态控件集合的正确方式。

第一步:重构组件的表单逻辑(TS代码)

先导入表单相关模块,然后用FormArray来存储每一行的表单数据,每一行对应一个包含code、name、price的FormGroup:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms';

@Component({
  selector: 'app-your-component',
  templateUrl: './your-component.component.html',
  styleUrls: ['./your-component.component.css']
})
export class YourComponent implements OnInit {
  addForm: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit(): void {
    // 初始化表单,默认先添加一行数据
    this.addForm = this.fb.group({
      items: this.fb.array([this.createItem()])
    });
  }

  // 创建单个行的表单组
  createItem(): FormGroup {
    return this.fb.group({
      code: [''],
      name: [''],
      price: ['']
    });
  }

  // 快捷获取FormArray的方法,模板里会用到
  get items(): FormArray {
    return this.addForm.get('items') as FormArray;
  }

  // 新增一行
  addFieldValue(): void {
    this.items.push(this.createItem());
  }

  // 删除指定索引的行
  deleteFieldValue(index: number): void {
    this.items.removeAt(index);
  }

  // 计算所有行的总价
  calculateTotal(): number {
    let total = 0;
    // 遍历每一行的价格,累加有效数值
    this.items.controls.forEach(item => {
      const price = parseFloat(item.get('price')?.value || '0');
      if (!isNaN(price)) {
        total += price;
      }
    });
    return total;
  }

  // 提交表单时获取所有数据
  onSubmit(): void {
    if (this.addForm.valid) {
      const allRowData = this.addForm.value.items;
      console.log('所有行的输入数据:', allRowData);
      const totalPrice = this.calculateTotal();
      console.log('计算出的总价:', totalPrice);
      // 这里可以添加后续的业务逻辑,比如提交到后端
    }
  }
}

第二步:修改模板的表格结构(HTML代码)

把原来的循环改成遍历FormArray的控件,给每一行绑定对应的formGroupName,确保每一行的输入都是独立的:

<form class="form-horizontal" (ngSubmit)="onSubmit()" [formGroup]="addForm">
  <table>
    <!-- 遍历所有动态行 -->
    <tr *ngFor="let item of items.controls; let i = index" [formGroupName]="i">
      <td><input type="text" formControlName="code" placeholder="输入编码"></td>
      <td><input type="text" formControlName="name" placeholder="输入名称"></td>
      <td><input type="number" formControlName="price" placeholder="输入价格"></td>
      <td><button type="button" (click)="deleteFieldValue(i)">Delete</button></td>
    </tr>
    <!-- 添加新行的按钮 -->
    <tr>
      <td colspan="4">
        <button type="button" (click)="addFieldValue()">Add more</button>
      </td>
    </tr>
    <!-- 实时显示总价 -->
    <tr>
      <td colspan="3" align="right"><strong>总价:</strong></td>
      <td>{{ calculateTotal() }}</td>
    </tr>
    <!-- 提交按钮 -->
    <tr>
      <td colspan="4">
        <button type="submit">提交数据</button>
      </td>
    </tr>
  </table>
</form>

关键说明

  • [formGroupName]="i":把当前行和FormArray中对应索引的FormGroup绑定,确保每一行的输入互不干扰。
  • 把价格输入改成type="number":既符合输入场景,也能避免用户输入非数字内容。
  • calculateTotal()方法:会自动遍历所有行的价格,处理空值或非数字的情况,确保计算准确。

这样改完之后,你点击Add more新增的每一行都会有独立的表单控件,提交时可以通过this.addForm.value.items拿到所有行的完整数据,总价也能实时计算显示了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:36:54