Skip to content

Commit 5a0ad41

Browse files
committed
94301: Trickle down errors to concat field inputs
When a concat group is marked as invalid ~ server error, its fields should also be marked as invalid
1 parent d88352f commit 5a0ad41

2 files changed

Lines changed: 76 additions & 3 deletions

File tree

src/app/shared/form/form.service.spec.ts

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,15 @@ describe('FormService test suite', () => {
108108
const title: AbstractControl = new FormControl(undefined, Validators.required);
109109
const date: AbstractControl = new FormControl(undefined);
110110
const description: AbstractControl = new FormControl(undefined);
111-
formGroup = new FormGroup({ author, title, date, description });
112-
controls = { author, title, date, description };
111+
112+
const addressLocation: FormGroup = new FormGroup({
113+
zipCode: new FormControl(undefined),
114+
state: new FormControl(undefined),
115+
city: new FormControl(undefined),
116+
});
117+
118+
formGroup = new FormGroup({ author, title, date, description, addressLocation });
119+
controls = { author, title, date, description , addressLocation };
113120
service = new FormService(builderService, store);
114121
})
115122
)
@@ -179,6 +186,30 @@ describe('FormService test suite', () => {
179186
expect(formGroup.controls.description.touched).toBe(true);
180187
});
181188

189+
it('should add errors to fields of group', () => {
190+
let control = controls.addressLocation;
191+
let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'addressLocation');
192+
let errorKeys: string[];
193+
194+
service.addErrorToField(control, model, 'Test error message');
195+
196+
// the group itself should get an error
197+
errorKeys = Object.keys(control.errors);
198+
expect(errorKeys.length).toBe(1);
199+
expect(control.hasError(errorKeys[0])).toBe(true);
200+
201+
expect(control.touched).toBe(true);
202+
203+
// the group's inputs should get an error
204+
Object.values(control.controls).forEach((subControl: AbstractControl) => {
205+
errorKeys = Object.keys(subControl.errors);
206+
expect(errorKeys.length).toBe(1);
207+
expect(subControl.hasError(errorKeys[0])).toBe(true);
208+
expect(subControl.touched).toBe(true);
209+
});
210+
211+
});
212+
182213
it('should remove error from field', () => {
183214
let control = controls.description;
184215
let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'description');
@@ -209,6 +240,30 @@ describe('FormService test suite', () => {
209240
expect(formGroup.controls.description.touched).toBe(false);
210241
});
211242

243+
it('should remove errors from fields of group', () => {
244+
let control = controls.addressLocation;
245+
let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'addressLocation');
246+
let errorKeys: string[];
247+
248+
service.addErrorToField(control, model, 'Test error message');
249+
errorKeys = Object.keys(control.errors);
250+
251+
service.removeErrorFromField(control, model, errorKeys[0]);
252+
253+
// the group itself should no longer have an error
254+
expect(errorKeys.length).toBe(1);
255+
expect(control.hasError(errorKeys[0])).toBe(false);
256+
expect(control.touched).toBe(false);
257+
258+
// the group's inputs should no longer have an error
259+
Object.values(control.controls).forEach((subControl: AbstractControl) => {
260+
errorKeys = Object.keys(subControl.errors);
261+
expect(errorKeys.length).toBe(1);
262+
expect(subControl.hasError(errorKeys[0])).toBe(false);
263+
expect(subControl.touched).toBe(false);
264+
});
265+
});
266+
212267
it('should reset form group', () => {
213268
const control = controls.author;
214269

src/app/shared/form/form.service.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { select, Store } from '@ngrx/store';
77
import { AppState } from '../../app.reducer';
88
import { formObjectFromIdSelector } from './selectors';
99
import { FormBuilderService } from './builder/form-builder.service';
10-
import { DynamicFormControlEvent, DynamicFormControlModel } from '@ng-dynamic-forms/core';
10+
import { DynamicFormControlEvent, DynamicFormControlModel, DynamicFormGroupModel } from '@ng-dynamic-forms/core';
1111
import { isEmpty, isNotUndefined } from '../empty.util';
1212
import { uniqueId } from 'lodash';
1313
import {
@@ -161,6 +161,15 @@ export class FormService {
161161
field.setErrors(error);
162162
}
163163

164+
// if the field in question is a group, pass down the error to its fields
165+
if (field instanceof FormGroup && model instanceof DynamicFormGroupModel) {
166+
model.group.forEach((subModel) => {
167+
const subField = field.controls[subModel.id];
168+
169+
this.addErrorToField(subField, subModel, message);
170+
});
171+
}
172+
164173
field.markAsTouched();
165174
}
166175

@@ -173,6 +182,15 @@ export class FormService {
173182
field.setErrors(error);
174183
}
175184

185+
// if the field in question is a group, clear the error from its fields
186+
if (field instanceof FormGroup && model instanceof DynamicFormGroupModel) {
187+
model.group.forEach((subModel) => {
188+
const subField = field.controls[subModel.id];
189+
190+
this.removeErrorFromField(subField, subModel, messageKey);
191+
});
192+
}
193+
176194
field.markAsUntouched();
177195
}
178196

0 commit comments

Comments
 (0)