【问题标题】:Angular 2 - form group componentAngular 2 - 表单组组件
【发布时间】:2017-02-15 03:32:56
【问题描述】:

我正在尝试构建一个数据驱动的表单,输入来自另一个组件,如下所示:

<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
    <app-form-group [name]="name"></app-form-group>
    <app-form-group [name]="email"></app-form-group>
    <app-form-group [name]="other"></app-form-group>
</form>

app-form-group 组件看起来像这样:

<div class="form-group">
    <label class="col-md-2 control-label">{{Name}}</label>
    <div class="col-md-9">
  <input class="form-control" [name]="name" [formControlName]="formCtrlName">
</div>

问题是formControlName 需要一个formGroupdirective,因此我得到这个错误:

Error : Error in ./FormGroupComponent class FormGroupComponent - inline template:3:58 caused by: formControlName must be used with a parent formGroup directive.You'll want to add a formGroup
   directive and pass it an existing FormGroup instance (you can create one in your class).

有没有办法解决这个问题?

【问题讨论】:

标签: angular angular2-forms


【解决方案1】:

您应该在app-form-group 组件中使用您的FormGroup [formGroup]="signupForm"。您可以使用此代码:

<div class="form-group" [formGroup]="signupForm">
  <label class="col-md-2 control-label">{{Name}}</label>
  <div class="col-md-9">
  <input class="form-control" [name]="name" [formControlName]="formCtrlName">
</div>

【讨论】:

  • 如何从app-form-group 子组件中看到signupForm?您不需要像 Bernhard Hochgatterer 的回答那样明确地传递它吗?
  • 您必须发送“Signuoform”作为输入
【解决方案2】:

您可以使用@Input 属性来获取对子组件的引用:

app-form-group.ts:

@Input('group')
public signupForm: FormGroup;

app.html:

<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
    <app-form-group [name]="name" [group]="signupForm"></app-form-group>
    <app-form-group [name]="name" [group]="signupForm"></app-form-group>
    <app-form-group [name]="name" [group]="signupForm"></app-form-group>
</form>

app-form-group.html:

<div class="form-group" [formGroup]="signupForm">
   <label class="col-md-2 control-label">{{Name}}</label>
   <div class="col-md-9">
   <input class="form-control" [name]="name" [formControlName]="formCtrlName">
</div>

有关详细信息,请查看本教程:https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2

【讨论】:

    【解决方案3】:

    当您想要实现自定义组件以将数据绑定到单个值时,正确的 Angular 方法是使用父视图指定 [formControl][formControlName] 的方法。

    <app-form-group formControlName="name"></app-form-group>
    <app-form-group formControlName="email"></app-form-group>
    <app-form-group formControlName="other"></app-form-group>
    

    在您的子控件中,您需要执行以下操作:

    首先将以下提供程序添加到您的 @Component 声明中,以便 Angular 知道您的组件可以使用 [formControlName] / [formControl]

    providers: [
      {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => CountrySelectorComponent),
        multi: true
      }
    ]
    

    然后您的子组件的类需要实现ControlValueAccessor 接口。这应该是一个完整的示例,如果没有,请告诉我,我会更改代码,我直接在浏览器中输入。

    @Component({
      // Ensure [formControl] or [formControlName] is also specified
      selector: '[formControl] app-form-group, [formControlName] app-form-group',
      templateUrl: './country-selector.component.html',
      styleUrls: ['./country-selector.component.scss'],
      providers: [
        {
          // Provide the value accessor
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => CountrySelectorComponent),
          multi: true
        }
      ]
    })
    export class CountrySelectorComponent implements ControlValueAccessor {
      private value: any;
      private hasHadFocus = false;
      private hasNotifiedTouched = false;
      private propagateChange: any = () => {};
      private propogateTouched: any = () => {};
    
      public changed(event: any) {
        this.value = event.srcElement.value;
        this.propagateChange(this.value);
      }
    
      /**
       * Called when (focus) is triggered
       */
      public focused() {
        this.hasHadFocus = true;
      }
    
      /**
       * Called when (blur) is triggered
       */
      public blurred() {
        if (this.hasHadFocus && !this.hasNotifiedTouched) {
          // Only notify once, and only if lost focus after a focus
          this.hasNotifiedTouched = true;
          this.propogateTouched();
        }
      }
    
      /**
       * Called when a new value is set via code
       * @param obj
       */
      writeValue(obj: any): void {
        this.value = obj;
      }
    
      /**
       * Register a call back to call when our value changes
       * @param fn
       */
      registerOnChange(fn: any): void {
        this.propagateChange = fn;
      }
    
      /**
       * Register a call back to call when our value is first touched
       * @param fn
       */
      registerOnTouched(fn: any): void {
        this.propogateTouched = fn;
      }
    }
    

    您的app-form-group 模板看起来像这样

    <div class="form-group">
        <label class="col-md-2 control-label">{{Name}}</label>
        <div class="col-md-9">
        <input class="form-control" (blur)="blurred()" focus="focussed()" change="changed($event)">
    </div>
    
    1. [formGroup]="signupForm" 添加到主视图中的每个app-form-group 实例
    2. 在您的 app-form-group 控件中实现 OnInit。
    3. private controlContainer: ControlContainer 添加到app-form-group 组件的构造函数中,以便Angular 将其注入
    4. public form: FormGroup; 属性添加到您的app-form-group 组件。
    5. 在 ngOnInit 中添加如下代码

      this.form = this.containerControl.control;

    在您的 app-form-group 模板中,您可以像这样添加 [formGroup]

    <div class="form-group" [formGroup]="form">
        <label class="col-md-2 control-label">{{Name}}</label>
        <div class="col-md-9">
      <input class="form-control" [name]="name" [formControlName]="formCtrlName">
    </div>
    

    这是需要最少代码量的方法,当您想要嵌入编辑多条数据(如地址)的复合控件时,我会推荐这种方法。

    来自这个博客 -> https://mrpmorris.blogspot.co.uk/2017/08/angular-composite-controls-formgroup-formgroupname-reactiveforms.html

    【讨论】:

      猜你喜欢
      • 2016-08-09
      • 2017-04-01
      • 2017-03-03
      • 2018-06-04
      • 2017-07-01
      • 2016-08-19
      • 2017-05-10
      • 1970-01-01
      • 2018-06-07
      相关资源
      最近更新 更多