Skip to content

Commit 52a5e76

Browse files
committed
feat(lib): handle FormArray
This closes #9
1 parent e1ba611 commit 52a5e76

File tree

3 files changed

+38
-33
lines changed

3 files changed

+38
-33
lines changed

projects/ngx-sub-form/src/lib/ngx-sub-form-utils.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,6 @@ export function subformComponentProviders(
5050

5151
const wrapAsQuote = (str: string): string => `"${str}"`;
5252

53-
export class ArrayNotTransformedBeforeWriteValueError extends Error {
54-
constructor() {
55-
super(
56-
`If you need to pass an array, please wrap it (for now) using "NgxSubFormRemapComponent" into an "array" property for example. Track direct array support here https://github.com/cloudnc/ngx-sub-form/issues/9`,
57-
);
58-
}
59-
}
60-
6153
export class MissingFormControlsError<T extends string> extends Error {
6254
constructor(missingFormControls: T[]) {
6355
super(

projects/ngx-sub-form/src/lib/ngx-sub-form.component.spec.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
NgxSubFormComponent,
77
NgxSubFormRemapComponent,
88
MissingFormControlsError,
9-
ArrayNotTransformedBeforeWriteValueError,
109
NGX_SUB_FORM_HANDLE_VALUE_CHANGES_RATE_STRATEGIES,
1110
} from '../public_api';
1211
import { Observable } from 'rxjs';
@@ -197,23 +196,24 @@ describe(`NgxSubFormComponent`, () => {
197196

198197
describe(`value is not null nor undefined`, () => {
199198
// we should be able to pass a value `false`, or an empty string for ex
200-
it(`should throw an error when the value is different than an object`, () => {
201-
const invalidValues: any[] = [1, true, false, '', 'some random string'];
202-
203-
// this could happen when using the setValue of patchValue on the top form as those methods are not strongly typed
204-
// but not using `subComponent.formGroup.patchValue` here as the error would not be caught here because not directly
205-
// called by that method
206-
invalidValues.forEach(value =>
207-
expect(() => subComponent.writeValue(value)).toThrow(
208-
new MissingFormControlsError(['color', 'canFire', 'numberOfPeopleOnBoard']),
209-
),
210-
);
211-
212-
const invalidArrays: any[] = [[], [1, 2, 3]];
213-
invalidArrays.forEach(value =>
214-
expect(() => subComponent.writeValue(value)).toThrow(new ArrayNotTransformedBeforeWriteValueError()),
215-
);
216-
});
199+
// todo: array
200+
// it(`should throw an error when the value is different than an object`, () => {
201+
// const invalidValues: any[] = [1, true, false, '', 'some random string'];
202+
203+
// // this could happen when using the setValue of patchValue on the top form as those methods are not strongly typed
204+
// // but not using `subComponent.formGroup.patchValue` here as the error would not be caught here because not directly
205+
// // called by that method
206+
// invalidValues.forEach(value =>
207+
// expect(() => subComponent.writeValue(value)).toThrow(
208+
// new MissingFormControlsError(['color', 'canFire', 'numberOfPeopleOnBoard']),
209+
// ),
210+
// );
211+
212+
// const invalidArrays: any[] = [[], [1, 2, 3]];
213+
// invalidArrays.forEach(value =>
214+
// expect(() => subComponent.writeValue(value)).toThrow(new ArrayNotTransformedBeforeWriteValueError()),
215+
// );
216+
// });
217217

218218
it(`should throw an error when the value is missing any of the required keys to create the form`, () => {
219219
expect(() => subComponent.writeValue({ randomValue: 'ok' } as any)).toThrow(

projects/ngx-sub-form/src/lib/ngx-sub-form.component.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
FormGroup,
77
ValidationErrors,
88
Validator,
9+
FormArray,
10+
FormControl,
911
} from '@angular/forms';
1012
import { merge, Observable, Subscription } from 'rxjs';
1113
import { delay, filter, map, startWith, withLatestFrom } from 'rxjs/operators';
@@ -15,7 +17,6 @@ import {
1517
ControlsNames,
1618
FormUpdate,
1719
MissingFormControlsError,
18-
ArrayNotTransformedBeforeWriteValueError,
1920
FormErrors,
2021
isNullOrUndefined,
2122
} from './ngx-sub-form-utils';
@@ -188,24 +189,36 @@ export abstract class NgxSubFormComponent<ControlInterface, FormInterface = Cont
188189

189190
const transformedValue: FormInterface = this.transformToFormGroup(obj);
190191

191-
// for now we throw an error if the transformed value isn't an object with all the expect values
192-
// there's an issue to track support for an array https://github.com/cloudnc/ngx-sub-form/issues/9
193-
if (Array.isArray(transformedValue)) {
194-
throw new ArrayNotTransformedBeforeWriteValueError();
195-
}
196-
197192
const missingKeys: (keyof FormInterface)[] = this.getMissingKeys(transformedValue);
198193
if (missingKeys.length > 0) {
199194
throw new MissingFormControlsError(missingKeys as string[]);
200195
}
201196

197+
this.handleFormArrayControls(transformedValue);
198+
202199
this.formGroup.setValue(transformedValue, {
203200
emitEvent: false,
204201
});
205202
this.formGroup.markAsPristine();
206203
this.formGroup.markAsUntouched();
207204
}
208205

206+
private handleFormArrayControls(obj: any) {
207+
Object.entries(obj).forEach(([key, value]) => {
208+
if (this.formGroup.get(key) instanceof FormArray && Array.isArray(value)) {
209+
const formArray: FormArray = this.formGroup.get(key) as FormArray;
210+
211+
while (formArray.length > value.length) {
212+
formArray.removeAt(formArray.length - 1);
213+
}
214+
215+
while (formArray.length < value.length) {
216+
formArray.push(new FormControl());
217+
}
218+
}
219+
});
220+
}
221+
209222
private getMissingKeys(transformedValue: FormInterface | null) {
210223
// `controlKeys` can be an empty array, empty forms are allowed
211224
const missingKeys: (keyof FormInterface)[] = this.controlKeys.reduce(

0 commit comments

Comments
 (0)