Search code examples
angulartypescript

Duplicates inside FormArray with more than one field


I need to validate that there are no duplicates inside a nested FormArray and I can't get my head wrapped around the solution I can do the validation for a single field inside the FormArray with RxwebValidators and unique but I fail miserably at finding what to do if I need to validate more than one field inside the form Array.

I have the follwing StackBlits, based off of another example, I want no repeated rows on the Skills section, any help will be highly appreciated.

https://stackblitz.com/edit/unique-value-validation-in-formarray-reactive-for-lepdkv?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts


Solution

  • You should use angular forms validators. Validator will trigger whenever value changes on control that it is being set. In your case you need to add it to skills formArray so that whenever anything is changed on it validator will be executed to check the validity.

          skills: this.formBuilder.array([this.getSkillFormGroup()], {
            validators: [
              (formArr: FormArray) => {
                const met = new Set<string>();
                return formArr.controls.some(({ value: { skillName, skull } }) => {
                  const val = `${skillName}__|__${skull}`;
                  if (met.has(val)) return true;
                  met.add(val);
                  return false;
                })
                  ? { hasDuplicates: true }
                  : null;
              },
            ],
          }),
    

    This implementation gonna work well if you dont need to highlight exact rows that are duplicated. If you need to show a general validation error that "something is duplicated"

    result: https://stackblitz.com/edit/unique-value-validation-in-formarray-reactive-for-qmtsvk?file=src%2Fapp%2Fapp.component.ts

    If you need to show errors on exact row then you will need to add validator on each skill formgroup that will go through form array and check if there is any duplication found with changed row, if there is any then will need to call also updateValueAndValidity on that duplication to make both rows marked as invalid. It's a bit more tricky solution but depends on your needs on how you want to show user invalid state