如何在 angular2 (ReactiveForms) 中添加动态自定义验证?

How to add dynamic custom validations in angular2 (ReactiveForms)?

我有一个要求,我想实现逻辑来动态地将对象数组数据分配给输入控件,并且基于更新我想更新我的数组,我想触发验证以检查是否输入 names/data在具有重复条目的控件中。 为了验证,我使用了 ReactiveForm 模块。但我面临以下 2 个问题 –

  1. 我如何创建相同的数组结构以便成功 验证我可以直接将更新的结构传递给 api?
  2. 我如何将数组对象的 id 分配给 formControlName,目前我正在为它分配循环索引。
    plunkar 参考这里 - https://plnkr.co/edit/RSBpT0sFSI1GDCp6K7VR?p=preview

组件:

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h3> Custom Group Validation</h3>
      <form [formGroup]="myForm">
          <div class="left">
              names: <br>
              <div formArrayName="names">
                  <div *ngFor="let item of namesArray.controls; let i = index">
                      <input type="text" [formControlName]="i">
                      <button (click)="removeAt(i)">X</button><br>
                  </div>
              </div>

              <div *ngIf="namesArray.hasError('duplicate')">
                  duplicate entries
              </div>
              <pre>Array value: <br>{{namesArray.value | json}}</pre>
          </div>
      </form>
</div>
  `
})

Class(摘要):

namesArray:FormArray =  new FormArray([], this.customGroupValidation  );
    dataArray: { custId: number, customerName: string }[] = [
{ custId: 101, customerName: 'John' },
{ custId: 102, customerName: 'Mike' },
{ custId: 103, customerName: 'Julia' }];

    ngOnInit():void{
      for(let ele of this.dataArray){
          this.namesArray.push(
            new FormControl(ele.customerName)
        );
      }
    }

感谢任何帮助!

处理这两个问题的一种方法是订阅 FormGroup 的 .valueChanges 事件,并放入检查方法以验证 FormControl 值是否存在重复情况。

在 ngOnInit() 中创建 FormControl 并将其添加到 FormGroup 时也分配 custId 属性

代码片段 -

import { Component, NgModule, OnInit } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormBuilder, FormGroup, FormArray, AbstractControl, Validators, FormControl, ReactiveFormsModule } from '@angular/forms'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h3> Custom Group Validation</h3>
      <form [formGroup]="customerFormGroup">
          <div class="left">
              names: <br>
              <div>
                  <div *ngFor="let item of dataArray">
                      <input type="text" [formControlName]="item.custId" [(ngModel)]="item.customerName">
                      <div *ngIf="customerFormGroup.controls[item.custId] && customerFormGroup.controls[item.custId].errors">
                        duplicate                       
                      </div>
                  </div>
              </div>
              <pre>Array value: <br>{{dataArray | json}}</pre>
          </div>
      </form>
</div>
  `
})
export class App implements OnInit {
  customerFormGroup: FormGroup = new FormGroup({});
  dataArray: { custId: number, customerName: string }[] = [
    { custId: 101, customerName: 'John' },
    { custId: 102, customerName: 'Mike' },
    { custId: 103, customerName: 'Julia' }];

  ngOnInit(): void {

    for (let ele of this.dataArray) {
      let control: FromControl = new FormControl(ele.customerName);
      this.customerFormGroup.addControl(ele.custId, control);
    }

    this.customerFormGroup.valueChanges.subscribe(
      data => this.onValueChanged(data)
    );
  }

  onValueChanged(data?: any) {
    if (!this.customerFormGroup) return;
    let formGroup = this.customerFormGroup;
    var result = _.groupBy(formGroup.controls, c => {
      if (c.value) return c.value.toLowerCase();
      else c.value;
    });
    for (let prop in result) {
      if (result[prop].length > 1) {
        _.forEach(result[prop], function (item: any) {
          if (item.dirty && item.value) {
            item.setErrors({
              'duplicate': true
            });
          }
        })
      }
    }
  }
}

@NgModule({
  imports: [BrowserModule, ReactiveFormsModule],
  declarations: [App],
  bootstrap: [App]
})
export class AppModule { }