From 99c7c2f0c738992278f84b85e292342ddd28dae9 Mon Sep 17 00:00:00 2001 From: Zak Henry Date: Tue, 19 Oct 2021 10:36:15 +1300 Subject: [PATCH] fix(FormArray validation): Ensure FormArray level validator errors are propagated to the parent subform --- projects/ngx-sub-form/src/lib/helpers.ts | 37 +++++++++---------- src/app/app.spec.e2e.ts | 1 + .../crew-members/crew-members.component.html | 5 ++- .../crew-members/crew-members.component.ts | 4 +- .../crew-members/crew-members.component.html | 5 ++- .../crew-members/crew-members.component.ts | 4 +- 6 files changed, 33 insertions(+), 23 deletions(-) diff --git a/projects/ngx-sub-form/src/lib/helpers.ts b/projects/ngx-sub-form/src/lib/helpers.ts index 752fb0cd..b8d02c11 100644 --- a/projects/ngx-sub-form/src/lib/helpers.ts +++ b/projects/ngx-sub-form/src/lib/helpers.ts @@ -1,13 +1,12 @@ -import { - AbstractControlOptions, - ControlValueAccessor, - FormArray, - FormControl, - FormGroup, - ValidationErrors, -} from '@angular/forms'; +import { AbstractControlOptions, ControlValueAccessor, FormArray, FormGroup, ValidationErrors } from '@angular/forms'; import { ReplaySubject } from 'rxjs'; import { Nilable } from 'tsdef'; +import { + ControlValueAccessorComponentInstance, + FormBindings, + NgxSubFormArrayOptions, + NgxSubFormOptions, +} from './ngx-sub-form.types'; import { ArrayPropertyKey, ControlsNames, @@ -15,12 +14,6 @@ import { OneOfControlsTypes, TypedFormGroup, } from './shared/ngx-sub-form-utils'; -import { - ControlValueAccessorComponentInstance, - FormBindings, - NgxSubFormArrayOptions, - NgxSubFormOptions, -} from './ngx-sub-form.types'; export const deepCopy = (value: T): T => JSON.parse(JSON.stringify(value)); @@ -83,6 +76,12 @@ export const getFormGroupErrors = ( const formErrors: NewFormErrors = Object.entries(formGroup.controls).reduce< Exclude, null> >((acc, [key, control]) => { + if (control.errors) { + // all of FormControl, FormArray and FormGroup can have errors so we assign them first + const accumulatedGenericError = acc as Record; + accumulatedGenericError[key as keyof ControlInterface] = control.errors; + } + if (control instanceof FormArray) { // errors within an array are represented as a map // with the index and the error @@ -98,12 +97,12 @@ export const getFormGroupErrors = ( } if (Object.values(errorsInArray).length > 0) { - const accHoldingArrays = acc as Record>; - accHoldingArrays[key as keyof ControlInterface] = errorsInArray; + const accumulatedArrayErrors = acc as Record>; + if (!(key in accumulatedArrayErrors)) { + accumulatedArrayErrors[key as keyof ControlInterface] = {}; + } + Object.assign(accumulatedArrayErrors[key as keyof ControlInterface], errorsInArray); } - } else if (control.errors) { - const accHoldingNonArrays = acc as Record; - accHoldingNonArrays[key as keyof ControlInterface] = control.errors; } return acc; diff --git a/src/app/app.spec.e2e.ts b/src/app/app.spec.e2e.ts index f60c80b9..0a73dc6b 100644 --- a/src/app/app.spec.e2e.ts +++ b/src/app/app.spec.e2e.ts @@ -242,6 +242,7 @@ context(`EJawa demo`, () => { }, crewMembers: { crewMembers: { + minimumCrewMemberCount: 2, 0: { firstName: { required: true, diff --git a/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-members.component.html b/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-members.component.html index a4b024c6..2f7b8182 100644 --- a/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-members.component.html +++ b/src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-members.component.html @@ -1,5 +1,8 @@
- Crew members form + + Crew members form + (Minimum 2) +
(this, { formType: FormType.SUB, formControls: { - crewMembers: new FormArray([]), + crewMembers: new FormArray([], { + validators: formControl => (formControl.value.length >= 2 ? null : { minimumCrewMemberCount: 2 }), + }), }, toFormGroup: (obj: CrewMember[]): CrewMembersForm => { return { diff --git a/src/app/main/listing/listing-form/vehicle-listing/crew-members/crew-members.component.html b/src/app/main/listing/listing-form/vehicle-listing/crew-members/crew-members.component.html index 329033ec..246484a5 100644 --- a/src/app/main/listing/listing-form/vehicle-listing/crew-members/crew-members.component.html +++ b/src/app/main/listing/listing-form/vehicle-listing/crew-members/crew-members.component.html @@ -1,5 +1,8 @@
- Crew members form + + Crew members form + (Minimum 2) +
{ protected getFormControls(): Controls { return { - crewMembers: new FormArray([]), + crewMembers: new FormArray([], { + validators: formControl => (formControl.value.length >= 2 ? null : { minimumCrewMemberCount: 2 }), + }), }; }