Angular嵌套FormArray内层FormControl无法获取选中值问题
问题原因
两个核心错误导致内层表单控件值无法同步:
- 数据源绑定错误:给mat-table传入的是
secondDataArray的值快照(即调用.value返回的普通对象数组),而非FormArray表单实例本身,渲染层和表单模型完全断开,用户输入无法回写到FormControl。 - 表单层级缺失:模板中直接在单元格内使用
formControlName="qtd",既没有在外层循环绑定外层FormGroup的上下文,也没有给表格行绑定对应索引的内层FormGroup,Angular表单无法定位qtd控件所属的父容器,值自然无法注册。
修复方案
1. 调整组件类代码,新增获取内层FormArray的辅助方法
避免模板中写复杂的类型转换,同时保证拿到的是表单实例而非值快照:
// 获取指定外层行索引对应的内层secondDataArray FormArray实例 getInnerFormArray(outerIndex: number): UntypedFormArray { return this.firstGroup.get(['dataArray', outerIndex, 'secondDataArray']) as UntypedFormArray; }
2. 修正模板表单层级与数据源绑定
重点修正四个位置:
- 外层循环渲染FormArray行时,必须绑定
formArrayName="dataArray"和对应索引的[formGroupName]="i",建立外层表单上下文 - mat-table的
[dataSource]直接绑定FormArray实例,不要调用.value取快照 - 内层表格的每一行通过索引绑定对应的内层FormGroup,给
qtd控件提供正确的父表单上下文 - 删除mat-select上多余的
name="qtd"属性,响应式表单不需要模板驱动表单的name标识,避免冲突
修正后的模板代码示例:
<!-- 根表单绑定 --> <div [formGroup]="firstGroup"> <!-- 外层FormArray绑定 --> <div formArrayName="dataArray"> <!-- 循环外层每一个FormGroup --> <div *ngFor="let outerItem of dataArray.controls; let i = index" [formGroupName]="i"> <!-- 外层必填项chooseOption1 --> <mat-form-field appearance="outline"> <mat-select formControlName="chooseOption1" placeholder="选择选项1"> <!-- 自行补充选项内容 --> </mat-select> </mat-form-field> <!-- 内层mat-table修正 --> <table mat-table [dataSource]="getInnerFormArray(i)" formArrayName="secondDataArray" class="mat-elevation-z8" > <ng-container matColumnDef="qtd"> <th mat-header-cell *matHeaderCellDef>QTD</th> <td mat-cell *matCellDef="let row; let innerIdx = index"> <!-- 绑定当前内层行的FormGroup --> <div [formGroupName]="innerIdx"> <mat-form-field appearance="outline"> <mat-select formControlName="qtd" placeholder="选择QTD"> <mat-option *ngFor="let ob of exampleData" [value]="ob"> {{ ob.symbol }} </mat-option> </mat-select> </mat-form-field> </div> </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayColumns"></tr> </table> <button type="button" (click)="addInnerLine(i)">添加内层行</button> </div> </div> <button type="button" (click)="addOuterLine()">添加外层行</button> </div>
验证方式
修改完成后选择qtd下拉选项,打印firstGroup.value即可看到dataArray下每一项的secondDataArray中,对应行的qtd字段已经正确同步选中的值,表单校验也能正常生效。
内容的提问来源于stack exchange,提问作者T.Aguiar
相关产品推荐
相关产品推荐

