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

时间:2017-03-21 18:37:46

标签: angular angular2-forms reactive-forms

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

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

    @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>
      `
    })
    

    类(摘要):

    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)
            );
          }
        }
    

    感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

处理这两个问题的一种方法是订阅FormGroup的.valueChanges事件,并使用check in方法验证FormControl值是否存在重复条件。

在ngOnInit()

中创建FormControl并将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 { }