【问题标题】:What is the difference between formControlName and FormControl?formControlName 和 FormControl 有什么区别?
【发布时间】:2026-01-15 17:25:01
【问题描述】:

我正在使用 Angular2 的ReactiveFormsModule 创建一个包含表单的组件。这是我的代码:

foo.component.ts

constructor(fb: FormBuilder) {
    this.myForm = fb.group({
        'fullname': ['', Validators.required],
        'gender': []
    });
}

foo.component.html(带有[formControl]):

<div class="fields">
    <div class="field">
        <label>Fullname*</label>
        <input type="text" [formControl]="myForm.controls.fullname"/>
    </div>
</div>

<div class="inline fields">
    <label for="gender">Gender</label>
    <div class="field">
        <div class="ui radio checkbox">
            <input type="radio" name="gender" checked="" tabindex="0" class="hidden" [formControl]="myForm.controls.gender">
            <label>Male</label>
        </div>
    </div>
    <div class="field">
        <div class="ui radio checkbox">
            <input type="radio" name="gender" tabindex="0" class="hidden" [formControl]="myForm.controls.gender">
            <label>Female</label>
        </div>
    </div>
</div>

foo.component.html(带有formControlName):

<div class="fields">
    <div class="field">
        <label>Fullname*</label>
        <input type="text" formControlName="fullname"/>
    </div>
</div>

<div class="inline fields">
    <label for="gender">Gender</label>
    <div class="field">
        <div class="ui radio checkbox">
            <input type="radio" name="gender" checked="" tabindex="0" class="hidden" formControlName="gender">
            <label>Male</label>
        </div>
    </div>
    <div class="field">
        <div class="ui radio checkbox">
            <input type="radio" name="gender" tabindex="0" class="hidden" formControlName="gender">
            <label>Female</label>
        </div>
    </div>
</div>

两种方式都有效。但我不知道使用[formControl]formControlName 有什么区别。

【问题讨论】:

  • 我会说使用 formControlName 而不是 formControl 的主要原因是您不想在组件中维护单个 FormControl 实例。

标签: angular radio-button angular2-forms form-control angular2-formbuilder


【解决方案1】:

我相信您错过了重要的一点:第二个示例中的[formGroup] 指令。 formControlName[formGroup] 一起使用来保存您的表单多点导航。例如:

<div>
  <input type="text" [formControl]="myForm.controls.firstName"/>
  <input type="text" [formControl]="myForm.controls.lastName"/>
  <input type="text" [formControl]="myForm.controls.email"/>
  <input type="text" [formControl]="myForm.controls.title"/>
</div>

相当于:

<div [formGroup]="myForm">
  <input type="text" formControlName="firstName"/>
  <input type="text" formControlName="lastName"/>
  <input type="text" formControlName="email"/>
  <input type="text" formControlName="title"/>
</div>

现在想象嵌套FormGroups :)

【讨论】:

  • 使用 [formControl]="form.get('Registration.Attributes.aboutme')" 导致问题.. 但与 formControlName="firstNRegistration.Attributes.aboutmeame" 一起工作正常
  • [formControl] 导致问题,而 form.valid 使用 formGroup 验证,任何 cmets
  • 如果输入元素是另一个组件,我该如何处理。如何将 fomrcontrol 与组件绑定
  • 过去两周我一直在工作中的一项活动中卡住,您的回答拯救了我。谢谢你!
【解决方案2】:

[formControl] 将对您创建的FormControl 实例的引用分配给FormControlDirective

formControlName 为表单模块分配一个字符串以按名称查找控件。

如果您为控件创建变量,您也不需要 Harry 提到的 .,但我也建议改用 [formGroup],因为对于更复杂的表单,这可能会变得混乱。

constructor(fb: FormBuilder) {
    this.fullName = new FormControl('', Validators.required);
    this.gender = new FormControl('');
    this.myForm = fb.group({
        'fullname': this.fullName,
        'gender': this.gender
    });
}

【讨论】:

  • 当我添加 this.fullName = new FormControl('', Validators.required);我收到一个错误,因为它是只读属性或常量,所以无法分配,但在这里我被视为变量。所以请帮助
  • 请发布确切错误消息。创建一个包含允许重现的代码的新问题可能会更好
【解决方案3】:

接受的答案中提供的两者有第 3 个等效项,即(不推荐):

<div [formGroup]="myForm">
  <input type="text" [formControl]="firstName"/>
  <input type="text" [formControl]="lastName"/>
  <input type="text" [formControl]="email"/>
  <input type="text" [formControl]="title"/>
</div>

请注意,我们仍在使用 [formGroup] 指令。

但是,为了使该模板编译时不会出错,您的组件需要将控件声明为 AbstractControls 而不是 FormControls:

myComponent.ts

firstName: AbstractControl
lastName: AbstractControl
email: AbstractControl
title: AbstractControl

但是,请注意声明 AbstractControls 是 not recommended,因此如果您收到错误 Cannot find control with unspecified name attribute,则可能是您混合了样式或将您的控件声明为 AbstractControls。

【讨论】:

  • 如果输入元素是另一个组件,我该如何处理。如何将 fomrcontrol 与组件绑定
  • 你不能——即使有办法,你也不应该。该元素应绑定到在该组件中定义的控件。如果要将数据传递给另一个组件,请使用服务(或者如果它是父组件,则使用事件发射器)。谷歌如何在组件之间传递数据
  • 你可以看看这个帖子*.com/questions/58100248/…
【解决方案4】:

来自 Angular 文档 (https://angular.io/guide/reactive-forms):

组件

@Component({
  ...
})
export class ProfileEditorComponent {
  profileForm = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
  });
}

模板

<form [formGroup]="profileForm">

  <label>
    First Name:
    <input type="text" formControlName="firstName">
  </label>

  <label>
    Last Name:
    <input type="text" formControlName="lastName">
  </label>

</form>

请注意,正如 FormGroup 包含一组控件一样, profileForm FormGroup 绑定到带有FormGroup 的表单元素 指令,在模型和模型之间创建一个通信层 包含输入的表单。 formControlName 输入由 FormControlName 指令将每个单独的输入绑定到表单 FormGroup中定义的控件

【讨论】:

    【解决方案5】:

    使用[formControl],您可以使用反应式编程优势,因为FormControl 有一个名为valueChanges 的属性(我现在知道这个,也许还有更多)它返回一个Observable,您可以订阅它并用它。 (例如,在注册场景中非常有用,您希望在用户更改值后检查输入电子邮件不重复)

    【讨论】:

    • 是的。但是您仍然在模板中使用 formControlName,即使在您的答案中使用模型时也是如此。只需将 formControlName="someFormControlName" 分配给 component.ts 文件中的 FormControl,例如 someFormControlName: FormControl;