Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reactive Form Array - Avoid Validation Error when push new elements

I have a form group which is composed by a single form array:

ngOnInit() {
    this.deviceDetailsFormGroup = this._formBuilder.group({
        deviceDetails: this._formBuilder.array([
            this.buildDeviceDetailsForm()
        ])
    });
}

Each control in the Form Array has required validators:

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

Below are my push and remove functions to the Form Array:

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

When I push new elements to the Form Array, they're marked as invalid although they're untouched and pristine. I understand that's caused by the Validators and empty default values set when I create the new FormGroup.

Is it possible to avoid this behavior so the FormArray elements are marked as errors only if they're touched ?

Thanks in advance.

like image 395
Luca Brasi Avatar asked Oct 23 '19 02:10

Luca Brasi


2 Answers

I had a very similar situation where whenever I added a new formGroup to my formArray its validations would get triggered even though they were untouched & pristine. Turns out if you use a button to dynamically add formGroups it will default the action to a submit event, triggering validations to run if you do not specify the button type.

Adding type="button" resolved the issue.

like image 65
Limerentfox Avatar answered Nov 04 '22 14:11

Limerentfox


Luca, the formControl in the FormArray will be invalid always, so the FormArray is invalid and the form is invalid. You need check if the control is touched. A simple example in this stackblitz. You see that if you add, the control is invalid, but not touched

The .html is a tipical form

<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>

And the .ts a "clasic"

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())
  }
like image 41
Eliseo Avatar answered Nov 04 '22 14:11

Eliseo