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

基于Angular Material表格与Form Array实现可新增行并回传数据的表单

实现带可编辑行的Angular Material表格表单

要完成可新增行、提交时将表格数据回传给父组件的Angular Material表格表单,需要结合FormArray来管理每一行的表单控件,以下是完整实现方案:

完善后的HTML代码

在你提供的基础上补充提交按钮,并确保表单结构与FormArray正确绑定:

<div class="flex-end-container">
  <button mat-raised-button color="primary" class="button" (click)="addRow()">
    <mat-icon matPrefix>add</mat-icon>
    New Row
  </button>
  <button mat-raised-button color="accent" class="button" (click)="submitForm()" style="margin-left: 10px;">
    <mat-icon matPrefix>send</mat-icon>
    Submit
  </button>
</div>
<form role="form" [formGroup]="dutyChartForm">
  <table mat-table [dataSource]="dataSource1">
    <!-- Member Type Column -->
    <ng-container matColumnDef="memberType">
      <th mat-header-cell class="header-row-border" *matHeaderCellDef>
        Select Staff
      </th>
      <td mat-cell *matCellDef="let element; let i = index" [formGroupName]="i">
        <mat-form-field class="common-input" appearance="outline">
          <mat-select formControlName="memberType" placeholder="Member Type">
            @for (data of memberTypeList; track data) {
              <mat-option [value]="data.value">{{data.viewValue}}</mat-option>
            }
          </mat-select>
        </mat-form-field>
      </td>
    </ng-container>

    <!-- Week Columns -->
    @for (column of weekColumns; track column) {
    <ng-container matColumnDef="{{ column }}">
      <th mat-header-cell class="header-row-border" *matHeaderCellDef>
        {{ column | titlecase }}
      </th>
      <td mat-cell *matCellDef="let element; let i = index" [formGroupName]="i">
        <mat-form-field
          class="common-input input-field"
          floatLabel="always"
          appearance="outline"
        >
          <input matInput id="{{column}}" formControlName="{{column}}" />
        </mat-form-field>
      </td>
    </ng-container>
    }

    <tr 
      mat-header-row
      class="header-row"
      *matHeaderRowDef="displayedColumns1"
    ></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns1; let i = index" [formGroupName]="i"></tr>
  </table>
</form>

对应的TypeScript代码

在组件类中初始化表单、定义数据列表、实现新增行和提交逻辑:

import { Component, Output, EventEmitter } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, Validators } from '@angular/forms';
import { MatTableDataSource } from '@angular/material/table';

@Component({
  selector: 'app-duty-chart-form',
  templateUrl: './duty-chart-form.component.html',
  styleUrls: ['./duty-chart-form.component.scss']
})
export class DutyChartFormComponent {
  @Output() formSubmitted = new EventEmitter<any[]>();
  dutyChartForm: FormGroup;
  dataSource1: MatTableDataSource<any>;
  memberTypeList = [
    { value: 'full-time', viewValue: 'Full Time Staff' },
    { value: 'part-time', viewValue: 'Part Time Staff' },
    { value: 'intern', viewValue: 'Intern' }
  ];
  weekColumns = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'];
  displayedColumns1: string[];

  constructor(private fb: FormBuilder) {
    // 初始化表单,包含一个FormArray用于存储行数据
    this.dutyChartForm = this.fb.group({
      rows: this.fb.array([])
    });
    // 配置显示列:成员类型 + 所有周列
    this.displayedColumns1 = ['memberType', ...this.weekColumns];
    // 初始化数据源
    this.updateDataSource();
    // 默认添加一行
    this.addRow();
  }

  // 获取FormArray实例
  get rows(): FormArray {
    return this.dutyChartForm.get('rows') as FormArray;
  }

  // 添加新行
  addRow(): void {
    // 创建一行的FormGroup,包含memberType和所有周列的控件
    const newRow = this.fb.group({
      memberType: ['', Validators.required],
      monday: [''],
      tuesday: [''],
      wednesday: [''],
      thursday: [''],
      friday: ['']
    });
    this.rows.push(newRow);
    this.updateDataSource();
  }

  // 更新表格数据源
  updateDataSource(): void {
    this.dataSource1 = new MatTableDataSource(this.rows.value);
    // 监听FormArray值变化,实时更新数据源
    this.rows.valueChanges.subscribe(() => {
      this.dataSource1.data = this.rows.value;
    });
  }

  // 提交表单,将数据传给父组件
  submitForm(): void {
    if (this.dutyChartForm.valid) {
      this.formSubmitted.emit(this.rows.value);
      // 可选:提交后清空表单
      // this.rows.clear();
      // this.addRow();
    } else {
      // 表单验证不通过时的处理
      this.dutyChartForm.markAllAsTouched();
    }
  }
}

关键实现说明

  • 表单结构:用FormGroup包裹一个FormArray,每一行都是独立的FormGroup,确保每一行的输入能被单独管理和验证。
  • 数据源同步:表格dataSource绑定到FormArray的value,通过valueChanges监听输入变化,实时更新表格数据。
  • 父组件通信:通过@Output定义formSubmitted事件,提交时将FormArray的有效值emit给父组件,父组件监听该事件即可获取数据。
  • 新增行逻辑:addRow方法向FormArray中push新的FormGroup,并更新数据源,表格会自动渲染新行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 12:41:04