基于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
相关产品推荐
相关产品推荐

