Angular使用Reactive Form实现对象数组输出的问题排查
问题核心原因
你当前的代码逻辑和想要的数据结构完全不匹配,问题出在两处:
- 你给
nb-select加了multiple多选属性,该组件本身的特性就是选中多个值时输出数组,直接绑定到单个siteId字段自然就会存成数组格式 - 你的
sitesFormArray初始化时仅创建了1个FormGroup元素,无论选多少个站点,数据都只会塞到这唯一的一个FormGroup里,最终自然得到长度为1、siteId为数组的结果
修复方案
你需要调整交互逻辑,让每个选中的站点对应FormArray里的一个独立FormGroup,有两种实现方式可选:
方案1:单选下拉+手动新增行(更通用的实现)
1. 修改HTML代码
<div class="col-md-3 select-site-btn"> <div formArrayName="sites"> <div *ngFor="let site of siteControls; let siteIndex = index" [formGroupName]="siteIndex"> <div class="form-group"> <label class="label" for="siteId">Site</label> <nb-select fullWidth placeholder="Select site" formControlName="siteId"> <nb-option *ngFor = "let site of sites" [value]="site.id" > {{site.name}} </nb-option> </nb-select> <button type="button" (click)="deleteSite(siteIndex)">删除当前站点</button> </div> </div> <button type="button" (click)="addSite()">新增站点</button> </div> </div>
2. 补充TS方法
// 新增站点行 addSite() { const sitesArray = this.Form.get('sites') as FormArray; sitesArray.push(this.Service.createSites()); } // 删除指定索引的站点行 deleteSite(index: number) { const sitesArray = this.Form.get('sites') as FormArray; sitesArray.removeAt(index); }
方案2:保留多选下拉,动态同步FormArray
如果你不想改多选交互,就监听多选下拉的值变化,动态调整FormArray的结构:
1. 修改HTML,给select加change事件
<nb-select multiple fullWidth placeholder="Select site" (change)="syncSites($event)"> <nb-option *ngFor = "let site of sites" [value]="site.id" > {{site.name}} </nb-option> </nb-select>
2. 补充TS同步方法
syncSites(event: any) { const selectedIds = event.values as number[]; const sitesArray = this.Form.get('sites') as FormArray; // 清空现有FormArray while (sitesArray.length) { sitesArray.removeAt(0); } // 按选中的id数量新建对应FormGroup selectedIds.forEach(id => { const group = this.Service.createSites(); group.patchValue({ Id: 218, // 你需要的Id值,根据实际业务调整 siteId: id }) sitesArray.push(group); }) }
修改后提交表单就能得到你期望的,每个站点对应一个独立对象、siteId为单个值的数组结构。
内容的提问来源于stack exchange,提问作者hanushic
相关产品推荐
相关产品推荐

