如何验证动态添加的表单字段的重复项

How to validate duplicates for dynamically added form field

我有一个来自调用的验证表单和一个名为 RepDetails 的表单数组,其中包含三个字段。默认情况下,表单显示三个字段。用户可以通过单击添加更多来添加更多详细信息。现在我想检查 Mydetails[0].name 是否应该与 mydetails[1].name 匹配。谁能帮忙解决这个问题

Myform = this.fb.group({   
    Mydetails: this.fb.array([this.createMydetails()])   
  });

createMydetails(): FormGroup {
    return this.fb.group({
      Myname: ['', Validators.required ],
      Myid: ['', Validators.required],
      Myphone: ['', Validators.required]
    });
  }

Html

<div
        formArrayName="Mydetails"
        *ngFor="let item of Mydetails.controls; let i = index"
      >
        <div [formGroupName]="i">
          <mat-form-field appearance="outline">
            <mat-label class="required">
              Name
            </mat-label>
            <input
              appAlphaNumeric
              [maxlength]="maxRepNamelen"
              formControlName="Myname"
              class="mat-body-1"
              matInput
            />
          </mat-form-field>
          <mat-form-field appearance="outline">
            <mat-label class="required">
              Id
            </mat-label>
            <input
              appAlphaNumeric
             
              formControlName="Myid"
              class="mat-body-1"
              matInput
            />
          </mat-form-field>
          <div class="phn-wrapper">
            <ngx-intl-tel-input
              [cssClass]="'int-phn'"
              [searchCountryField]="[
                SearchCountryField.Iso2,
                SearchCountryField.Name
              ]"name="phone"
              formControlName="Myphone"
            >
            </ngx-intl-tel-input>
          </div>
          <mat-icon
            *ngIf="Mydetails.length > 1"
            (click)="remove(i)"
            class="close"
            >close</mat-icon
          >
          
        </div>
      </div>
        class="add-fields"
        (click)="add()"
      >
        <mat-icon class="icon">add_circle_outline</mat-icon>
        <span class="text mat-button">
          {{"ADD MORE"}}</span
        >
      </div>

this SO 中,您对 FormArray 进行了自定义验证。如果您在 formArray 上使用自定义验证,则问题是您始终会检查您更改 formArray 中的任何值(repName、passport 或 phoneName 中的任何更改)

您可以在考虑其他控件的表单控件上创建自定义验证器

  checkIfUnique(index) {
    return (control: FormControl) => {
      //try get the form array
      //control.parent is the FormGroup, control.parent.parent is the formArray
      const formArray =
        control.parent && control.parent.parent
          ? (control.parent.parent as FormArray)
          : null;
      if (formArray && formArray.controls.length) {
        for (let i = index - 1; i >= 0; i--) {
          if (
            (formArray.at(i) as FormGroup).get("repName").value == control.value
          )
            return { errorRepeat: true };
        }
      }
    };
  }

您需要在创建formArray 的formGroup 时,将元素的“索引”传递给验证器。所以你需要改变你的功能 createRep

//pass the index
createRep(index:number): FormGroup {
    return this.fb.group({
      repName: ['', [Validators.required,this.checkIfUnique(index) ]],
      passport: ['', Validators.required],
      phoneNumber: ['', Validators.required]
    });
  }

好吧,我们最后需要的是,当更改任何 'repName' 的值时,检查其余控件。请记住,Angular 检查您更改的 formControl,而不是其余部分,因此如果 repName[0]="a"repName[1]="b",当将 repName[0] 更改为“b”时 Angular 不要'检查 repName[1]。所以我们创建一个函数

  checkFormArray()
  {
    this.detailsFormArray.controls.forEach(x=>{
      (x as FormGroup).get('repName').updateValueAndValidity()
    })
  }
  //I use a getter of the formArray
  get detailsFormArray() {
     return (this.verificationForm.get("repDetails") as FormArray)
  }

然后在输入中调用函数

  <input formControlName="repName" (input)="checkFormArray()">

你可以see the stackblitz

注意:我从你的问题中删除了标签 angularjs(你的问题只是关于 angular)