1
votes

I'm using Angular 6 with reactive forms. One of the form field is a FormArray which adds controls as the user clicks an Add button.

Within the FormArray, I would like to check whether the FormControl value already exists in the FormArray.

This works fine until the user clicks 'Add' button which resets the previous control error and marks the control as valid although it still has a duplicate value.

This is the function to add control in the form array:

onAddIPAddress() {

  if (( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).length < 8) {

    const control = new FormControl(null, Validators.compose([
      Validators.required,
      Validators.pattern(this.ipaddressPattern),
      this.forbiddenIPs.bind(this),
      this.onDuplicateIPFormArray.bind(this)
    ]));


    ( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).push(control);


  } else {
    return;
  }

}

Then, this is the custom validator code:

onDuplicateIPFormArray(control: FormControl): {
  [s: string]: boolean
} {

  if (
    ( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).length > 1 &&
    !( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).value.includes(null) &&
    ( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).value.indexOf(control.value) !== -1)

  {
    console.log(( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).value.indexOf(control.value));

    return {
      duplicateIP: true
    };
  }

  return null;

}

From the console, I can see the IndexOf value is incorrect but not able to understand why.

Any ideas how I can handle this ?

Thanks

1
As far as I understand it, you set the value of the newly created FormControl to null and afterwards use null for the indexOfMatthias Sommer
I set the initial FormControl value to null and then in the validator do the followings: - Check the FormArray length is > 1, - Check if one of the FormArray control is not null and if none is null use get the indexOf the FormControl valueLuca Brasi

1 Answers

2
votes

Ok, so I've changed how validation should be done and it seems much better:

  • Remove custom Validator from individual FormArray controls.

  • Put the duplicate items custom validator on the FormArray itself.

if ($event.value ===
  'ip-address') {
  this.tcpudpAppFormGroup.addControl('ipaddressArray', new FormArray([], Validators.compose([
    Validators.required,
    this.onDuplicateIPFormArray.bind(this)

  ])));

Then create the FormArray validator as a standard function to detect duplicated items in an array:

onDuplicateIPFormArray() {

  if (( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray'))) {

    let counts = [];

    for (let i = 0; i < ( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).length; i++) {
      if (counts[( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).value[i]] === undefined) {
        counts[( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).value[i]] = 1;
      } else {
        console.log(counts);
        ( < FormArray > this.tcpudpAppFormGroup.get('ipaddressArray')).controls[i].setErrors({
          duplicateIP: true
        });
        
      }
    }
  }
}