Angular 2 - 表单组组件

Angular 2 - form group component

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

<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 需要一个 formGroup 指令,因此我得到这个错误:

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).

有什么办法可以解决这个问题吗?

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

<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>

您可以使用@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>

应用程序表单-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

当您想要实现自定义组件以将数据绑定到单个值时,正确的 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
  }
]

您的子组件的 class 然后需要实现 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