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

Angular中如何让嵌套表单组返回对象数组?

解决方案

要把residences从单个FormGroup改成对象数组,你需要使用Angular的FormArray来实现,以下是具体实现步骤:

1. 更新组件代码(form.component.ts)

先导入FormArray和FormBuilder(FormBuilder能简化表单构建逻辑),再重构表单结构:

import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators, FormArray, FormBuilder } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css'],
})
export class FormComponent {
  public form: FormGroup;

  constructor(private fb: FormBuilder) {
    // 初始化表单,residences设为FormArray,默认包含一个住址表单组
    this.form = this.fb.group({
      first_name: ['', Validators.required],
      last_name: ['', Validators.required],
      email: ['', [Validators.required, Validators.email]],
      phone: ['', Validators.required],
      residences: this.fb.array([this.createResidenceGroup()])
    });
  }

  // 快捷获取residences对应的FormArray实例
  get residencesArray(): FormArray {
    return this.form.get('residences') as FormArray;
  }

  // 创建单个住址的FormGroup
  createResidenceGroup(): FormGroup {
    return this.fb.group({
      city: [''],
      address: ['']
    });
  }

  // 添加新的住址表单
  addResidence(): void {
    this.residencesArray.push(this.createResidenceGroup());
  }

  // 删除指定索引的住址表单
  removeResidence(index: number): void {
    this.residencesArray.removeAt(index);
  }

  public sendFormData() {
    console.log(this.form.value);
    // 此时residences会输出对象数组,格式示例:[{city: '北京', address: 'XX街道'}, ...]
  }
}

2. 更新模板代码(form.component.html)

需要遍历residencesArray渲染每个住址的表单控件,同时添加添加/删除按钮:

<form [formGroup]="form" (ngSubmit)="sendFormData()">
  <!-- 基础信息表单部分 -->
  <div>
    <label>First Name:</label>
    <input formControlName="first_name" />
    <div *ngIf="form.get('first_name')?.invalid && form.get('first_name')?.touched">
      First name is required
    </div>
  </div>

  <div>
    <label>Last Name:</label>
    <input formControlName="last_name" />
    <div *ngIf="form.get('last_name')?.invalid && form.get('last_name')?.touched">
      Last name is required
    </div>
  </div>

  <div>
    <label>Email:</label>
    <input formControlName="email" type="email" />
    <div *ngIf="form.get('email')?.invalid && form.get('email')?.touched">
      {{form.get('email')?.errors?.['required'] ? 'Email is required' : 'Invalid email format'}}
    </div>
  </div>

  <div>
    <label>Phone:</label>
    <input formControlName="phone" />
    <div *ngIf="form.get('phone')?.invalid && form.get('phone')?.touched">
      Phone is required
    </div>
  </div>

  <!-- 住址数组表单部分 -->
  <div formArrayName="residences">
    <h3>Residences</h3>
    <button type="button" (click)="addResidence()">Add New Residence</button>
    
    <div *ngFor="let residence of residencesArray.controls; let i = index" [formGroupName]="i">
      <h4>Residence {{i + 1}}</h4>
      <button type="button" (click)="removeResidence(i)" *ngIf="residencesArray.length > 1">Remove</button>
      
      <div>
        <label>City:</label>
        <input formControlName="city" />
      </div>
      <div>
        <label>Address:</label>
        <input formControlName="address" />
      </div>
    </div>
  </div>

  <button type="submit" [disabled]="form.invalid">Submit</button>
</form>

核心说明

  • FormArray是Angular表单模块专门用于管理表单控件数组的类,每个元素对应一个FormGroup(即单个住址对象)
  • 用get residencesArray()的getter方法可以快速获取FormArray实例,简化模板和组件内的调用逻辑
  • createResidenceGroup()封装了单个住址表单的创建逻辑,提升代码复用性
  • 模板中通过formArrayName绑定数组,用*ngFor遍历数组控件,再通过formGroupName绑定索引关联每个子表单组

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 07:45:29