从反应形式角度中的元素自动创建FormControls

时间:2018-08-08 06:53:17

标签: angular angular-reactive-forms angular-forms

如您所知,当我们使用Angular中的“反应式表单”创建表单时,我们将formcontrolname分配给元素,并手动创建如下所示的formcontrol:

<form   [formGroup]="ntForm" (change)="onChange($event)" (ngSubmit)="onSubmit()" class="nt-form">
  <mat-form-field class="example-full-width">
    <input  matInput placeholder="User Id" formControlName="userId" [min]="5">
    <mat-error >{{getErrors('userId')}}</mat-error>
  </mat-form-field>

  <mat-form-field class="example-full-width">
    <input matInput placeholder="Id"  formControlName="id" required [min]="10">
    <mat-error >{{getErrors('id')}}</mat-error>
  </mat-form-field>

  <mat-form-field class="example-full-width">
    <input matInput placeholder="Title" formControlName="title" [email]="true">
    <mat-error >{{getErrors('title')}}</mat-error>
  </mat-form-field>

  <button class="nt-form-button" type="submit">Submit</button>

手动添加表单控件:

 this.ntForm = this.form.group({
      'id': new FormControl('id'),
      'userId': new FormControl('userId'),
      'title': new FormControl('title')   
    });

这乍看起来似乎很简单,但是如果我们有20个元素呢? 我们需要手动添加名称并进行维护。在敏捷开发中,这将是痛苦的。 为了解决这个问题,我创建了一个函数,该函数根据formControlName属性自动创建控件:

 fillControls(data) {
    const els: any = document.getElementsByClassName('nt-form')[0]
      .querySelectorAll('[formControlName]');
    els.forEach(node => {
      const controlName = node.attributes['formcontrolname'].nodeValue;
      this.ntForm.addControl(controlName, new FormControl('', []));
    });
  }

但是使用这种方法会发出错误消息(“找不到名称为''的控件),因为我首先用空控件初始化表单并将其填充。 我怎么解决这个问题?谢谢

1 个答案:

答案 0 :(得分:3)

我认为您做错了。

您应该从TS中获取控件名称,并从HTML中对其进行迭代,而不是从HTML中获取控件名称。

例如,您可以使用界面创建表单控件,使用静态方法从中创建表单组,然后遍历HTML中的界面元素。

export interface ReactiveFormControl {
  name: string;
  placeholder: string;
  defaultValue: string;
  validators: Validators[];
}

export class ReactiveFormUtils {
  public static toFormGroup(builder: FormBuilder, controls: ReactiveFormControl[]) {
    const form = {};
    controls.forEach(control => form[control.name] = [control.defaultValue, [...control.validators]]);
    return builder.group(form);
  }

  public static getControlNames(controls: ReactiveFormControl[]) {
    return controls.map(control => control.name);
  }
}