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

Angular 13中如何将FormGroup属性绑定到子组件?

Angular嵌套表单控件绑定与FormArray子组件传递解决方案

问题概述

父组件初始化包含嵌套FormGroup(profile)和两个FormArray(addresses、identifications)的表单组,通过@Input将根表单组传递给UsersProfileComponent子组件后,子组件绑定profile下的firstname控件时触发错误:ERROR Error: Cannot find control with name: 'firstname'。同时需实现addresses传递给UsersAddressComponent、identifications传递给UsersIdentificationComponent的表单绑定。

父组件核心表单代码:

formUsersInformation: FormGroup = this.formBuilder.group({
  profile: this.formBuilder.group({
    firstname: new FormControl('', [Validators.required, Validators.minLength(2)]),
    middlename: new FormControl('', [Validators.required, Validators.minLength(2)]),
    lastname: new FormControl('', [Validators.required, Validators.minLength(2)]),
    birthdate: new FormControl('', [Validators.required]),
    civilstatus: new FormControl('', [Validators.required, Validators.minLength(2)]),
    emailaddress: new FormControl('', [Validators.required, Validators.email]),
    phonenumber: new FormControl('', [Validators.required, Validators.pattern('^[0-9]+$')])
  }),
  addresses: this.formBuilder.array([
    this.formBuilder.group({
      idtype: new FormControl('', [Validators.required]),
      idnumber: new FormControl('', [Validators.required]),
      idexpiration: new FormControl('', [Validators.required]),
      idfile: new FormControl('', [Validators.required]),
    })
  ]),
  identifications: this.formBuilder.array([
    this.formBuilder.group({
      street: new FormControl('', [Validators.required]),
      city: new FormControl('', [Validators.required]),
      state: new FormControl('', [Validators.required]),
      zipcode: new FormControl('', [Validators.required])
    })
  ]),
});

父组件传递表单给子组件的代码:

<app-users-profile 
  [formUsersProfile]="formUsersInformation" 
  (FormActionEvent)="formsAction($event)" 
  *ngIf="isUsersProfileVisible">
</app-users-profile>

子组件接收输入的代码:

@Input() formUsersProfile: FormGroup = new FormGroup({});

原错误子组件HTML代码:

<div class="row" [formGroup]="formUsersProfile">
  <div class="col-md-4 mb-4">
      <label for="firstname" class="form-label">First Name</label>
      <input type="text" class="form-control radius-none"  formControlName="firstname"  id="firstname">
  </div>
</div>

错误原因

子组件模板中直接将根表单组formUsersProfile绑定为当前表单上下文,但firstname控件属于根表单组下的嵌套FormGroup(profile),而非根表单组的直接控件,因此formControlName="firstname"无法找到对应控件。

解决方案

1. 修复UsersProfileComponent的嵌套表单绑定

有两种方式实现正确绑定:

方式一:模板中使用formGroupName指定嵌套表单组

修改子组件HTML,在根表单组绑定的容器内,添加formGroupName="profile"的容器,将表单上下文切换到profile嵌套组:

<div class="row" [formGroup]="formUsersProfile">
  <!-- 切换到profile嵌套FormGroup -->
  <div formGroupName="profile">
    <div class="col-md-4 mb-4">
        <label for="firstname" class="form-label">First Name</label>
        <input type="text" class="form-control radius-none" formControlName="firstname" id="firstname">
    </div>
    <!-- 其他profile控件(middlename、lastname等)同理放在此容器内 -->
  </div>
</div>

方式二:子组件中定义getter获取嵌套表单组

在子组件类中添加getter,直接获取profile嵌套组,模板中绑定此getter作为表单上下文:

@Input() formUsersProfile: FormGroup = new FormGroup({});

// 获取profile嵌套FormGroup
get profileForm(): FormGroup {
  return this.formUsersProfile.get('profile') as FormGroup;
}

修改子组件HTML:

<div class="row" [formGroup]="profileForm">
  <div class="col-md-4 mb-4">
      <label for="firstname" class="form-label">First Name</label>
      <input type="text" class="form-control radius-none" formControlName="firstname" id="firstname">
  </div>
  <!-- 其他profile控件直接在此容器内绑定 -->
</div>

2. 实现FormArray传递与子组件绑定

步骤1:父组件中定义FormArray的getter

在父组件类中添加getter,方便获取addresses和identifications两个FormArray:

// 获取addresses FormArray
get addressesFormArray(): FormArray {
  return this.formUsersInformation.get('addresses') as FormArray;
}

// 获取identifications FormArray
get identificationsFormArray(): FormArray {
  return this.formUsersInformation.get('identifications') as FormArray;
}

步骤2:父组件传递FormArray给对应子组件

修改父组件HTML,将两个FormArray分别传递给子组件:

<!-- 传递addresses FormArray给UsersAddressComponent -->
<app-users-address 
  [addressesFormArray]="addressesFormArray"
  *ngIf="isUsersProfileVisible">
</app-users-address>

<!-- 传递identifications FormArray给UsersIdentificationComponent -->
<app-users-identification 
  [identificationsFormArray]="identificationsFormArray"
  *ngIf="isUsersProfileVisible">
</app-users-identification>

步骤3:子组件接收FormArray并绑定模板

UsersAddressComponent实现

子组件类接收输入:

import { Component, Input } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';

@Component({
  selector: 'app-users-address',
  templateUrl: './users-address.component.html',
  styleUrls: ['./users-address.component.css']
})
export class UsersAddressComponent {
  @Input() addressesFormArray: FormArray = new FormArray([]);
}

子组件HTML模板绑定FormArray:

<!-- 绑定根表单组(确保FormArray上下文正确) -->
<div [formGroup]="addressesFormArray.parent as FormGroup">
  <!-- 指定FormArray名称 -->
  <div formArrayName="addresses">
    <!-- 循环遍历FormArray中的每个FormGroup -->
    <div *ngFor="let address of addressesFormArray.controls; let i = index" [formGroupName]="i" class="mb-3">
      <div class="col-md-3 mb-2">
        <label for="idtype-{{i}}" class="form-label">ID Type</label>
        <input type="text" class="form-control radius-none" formControlName="idtype" id="idtype-{{i}}">
      </div>
      <div class="col-md-3 mb-2">
        <label for="idnumber-{{i}}" class="form-label">ID Number</label>
        <input type="text" class="form-control radius-none" formControlName="idnumber" id="idnumber-{{i}}">
      </div>
      <!-- 其他address控件(idexpiration、idfile)同理绑定 -->
    </div>
  </div>
</div>
UsersIdentificationComponent实现

子组件类接收输入:

import { Component, Input } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';

@Component({
  selector: 'app-users-identification',
  templateUrl: './users-identification.component.html',
  styleUrls: ['./users-identification.component.css']
})
export class UsersIdentificationComponent {
  @Input() identificationsFormArray: FormArray = new FormArray([]);
}

子组件HTML模板绑定FormArray:

<div [formGroup]="identificationsFormArray.parent as FormGroup">
  <div formArrayName="identifications">
    <div *ngFor="let id of identificationsFormArray.controls; let i = index" [formGroupName]="i" class="mb-3">
      <div class="col-md-3 mb-2">
        <label for="street-{{i}}" class="form-label">Street</label>
        <input type="text" class="form-control radius-none" formControlName="street" id="street-{{i}}">
      </div>
      <div class="col-md-3 mb-2">
        <label for="city-{{i}}" class="form-label">City</label>
        <input type="text" class="form-control radius-none" formControlName="city" id="city-{{i}}">
      </div>
      <!-- 其他identification控件(state、zipcode)同理绑定 -->
    </div>
  </div>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:45:35