Angular响应式表单如何将FormGroup推入嵌套FormArray
Angular响应式表单动态新增训练组功能实现方案
你的现有代码逻辑方向正确,但存在TypeScript类型校验不通过、嵌套控件访问不规范的问题,按以下方式调整即可稳定运行:
核心问题说明
直接通过.controls[0].controls.sets链式访问嵌套控件时,TypeScript无法自动推导AbstractControl的具体类型,编译阶段会抛出类型错误,硬编码索引和重复的访问逻辑也不利于后续维护。
修正后的完整实现
import { Component, OnInit } from '@angular/core'; import { FormArray, FormControl, FormGroup } from '@angular/forms'; @Component({ selector: 'app-workout-record', templateUrl: './workout-record.component.html' }) export class WorkoutRecordComponent implements OnInit { workoutForm!: FormArray; ngOnInit() { this.workoutForm = new FormArray([ new FormGroup({ name: new FormControl(''), sets: new FormArray([ this.createSingleSetGroup() ]) }) ]); } // 封装getter快速访问嵌套的sets表单数组,统一做类型断言 get setsList(): FormArray { return this.workoutForm.at(0).get('sets') as FormArray; } // 抽离单组训练的表单组创建逻辑,避免重复代码 private createSingleSetGroup(): FormGroup { return new FormGroup({ reps: new FormControl(null), weight: new FormControl(null) }); } // 新增训练组方法 public addSet() { this.setsList.push(this.createSingleSetGroup()); } // 可选:配套训练组删除方法 public removeSet(index: number) { this.setsList.removeAt(index); } }
模板层配套绑定示例
<!-- 绑定第一个训练动作的表单组 --> <form [formGroup]="workoutForm.at(0)"> <div class="action-name"> <label>训练动作名称</label> <input type="text" formControlName="name" placeholder="例:杠铃卧推"> </div> <!-- 绑定sets嵌套表单数组 --> <div formArrayName="sets"> <h4>训练组记录</h4> <div *ngFor="let set of setsList.controls; let i = index" [formGroupName]="i" class="set-item"> <span>第{{i+1}}组</span> <label> 次数: <input type="number" formControlName="reps" min="1"> </label> <label> 重量(kg): <input type="number" formControlName="weight" min="0" step="0.5"> </label> <button type="button" (click)="removeSet(i)">删除本组</button> </div> </div> <button type="button" (click)="addSet()" class="add-btn">+ 新增训练组</button> </form>
扩展提示:如果后续需要支持多个训练动作录入(即workoutForm这个FormArray中存在多个动作FormGroup),只需要把getter中硬编码的0索引改为动态传入的动作下标即可,不需要改动核心逻辑。
内容的提问来源于stack exchange,提问作者nandesuka
相关产品推荐
相关产品推荐

