反应式表单数组 - 推送新元素时避免验证错误

Luc*_*asi 3 angular angular-reactive-forms

我有一个由单个表单数组组成的表单组:

ngOnInit() {
    this.deviceDetailsFormGroup = this._formBuilder.group({
        deviceDetails: this._formBuilder.array([
            this.buildDeviceDetailsForm()
        ])
    });
}
Run Code Online (Sandbox Code Playgroud)

Form Array 中的每个控件都需要验证器:

buildDeviceDetailsForm(): FormGroup {
    return this._formBuilder.group({
        ipAddressCtrl: [
            "",
            [Validators.pattern(ipaddressPattern), Validators.required]
        ],
        hostnameCtrl: [
            "",
            [
                Validators.required,
                Validators.maxLength(30),
                Validators.minLength(5)
            ]
        ]
    });
}
Run Code Online (Sandbox Code Playgroud)

下面是我对 Form Array 的 push 和 remove 函数:

addNewDevice() {
    this.deviceItems = this.deviceDetailsFormGroup.get(
        "deviceDetails"
    ) as FormArray;

    if (this.deviceItems.length > MAX_DEVICES) {
        this.toastNotif.errorToastNotif(
            `A maximum of ${MAX_DEVICES} devices can be selected for a single job scan`,
            "Too many devices selected"
        );
        return;
    }

    if (this.deviceDetailsFormGroup.invalid) {
        return;
    }

    let mapIP = new Map<string, number>();

    // Warn about duplicate IP's in form
    this.deviceItems.controls.forEach(ctrl => {
        if (mapIP[ctrl.value.ipAddressCtrl] === 0) {
            this.toastNotif.warningToastNotif(
                "You have entered duplicate IP's in the form fields",
                "Duplicate" + " IP's"
            );
        }

        mapIP[ctrl.value.ipAddressCtrl] = 0;
    });

    this.deviceItems.push(this.buildDeviceDetailsForm());
}

removeDevice(i: number) {
    this.deviceItems.removeAt(this.deviceItems.length - 1);
}
Run Code Online (Sandbox Code Playgroud)

当我将新元素推送到 Form Array 时,它们被标记为无效,尽管它们未受影响且原始。我知道这是由验证器和创建新的时设置的空默认值引起的FormGroup.

是否可以避免这种行为,以便FormArray元素仅在被触摸时才被标记为错误?

提前致谢。

小智 12

我有一个非常相似的情况,每当我formGroup向我formArray的验证添加新内容时,即使它们是untouched&也会被触发pristine。事实证明,如果您使用按钮动态添加formGroups它会将操作默认为提交事件,如果您未指定按钮类型,则会触发验证运行。

添加type="button"解决了问题。


Eli*_*seo 6

Luca,FormArray 中的formControl 会一直无效,所以FormArray 无效,表单无效。您需要检查是否触摸了控件。此 stackblitz 中的一个简单示例。你看你加的话,控件无效,但是没碰过

.html 是一种典型的形式

<button (click)="add()">Add</button>
<form [formGroup]="myForm">
<div formArrayName="myFormArray">
  <div *ngFor="let group of myFormArray.controls;let i=index" [formGroupName]="i">
       <input formControlName="name">
       <!--show only after touched and invalid-->
       <div *ngIf="group.get('name').touched && group.get('name').invalid">
         invalid and touched
       </div>
       <!--show always when add a new formGroup to array-->
       <div *ngIf="group.get('name').invalid">
         invalid 
       </div>
  </div>
  </div>
  </form>
Run Code Online (Sandbox Code Playgroud)

.ts 是“经典”

myForm=new FormGroup({
     myFormArray:new FormArray([])
  })

  get myFormArray()
  {
    return this.myForm.get('myFormArray') as FormArray
  }
  createGroup()
  {
    return new FormGroup({
      name:new FormControl('',Validators.required)
    })
  }
  add()
  {
    this.myFormArray.push(this.createGroup())
  }
Run Code Online (Sandbox Code Playgroud)