Skip to content

Commit 1a9e62d

Browse files
committed
feat(Form Arrays): Add typesafety to form array option type
1 parent 3f2d02c commit 1a9e62d

File tree

4 files changed

+30
-27
lines changed

4 files changed

+30
-27
lines changed

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export function createFormDataFromOptions<ControlInterface, FormInterface>(
155155
export const handleFArray = <FormInterface>(
156156
formArrayWrappers: FormArrayWrapper<FormInterface>[],
157157
obj: FormInterface,
158-
createFormArrayControl: NgxSubFormArrayOptions<FormInterface>['createFormArrayControl'] | null,
158+
createFormArrayControl: Required<NgxSubFormArrayOptions<FormInterface>>['createFormArrayControl'],
159159
) => {
160160
if (!formArrayWrappers.length) {
161161
return;
@@ -177,11 +177,7 @@ export const handleFArray = <FormInterface>(
177177
}
178178

179179
for (let i = control.length; i < value.length; i++) {
180-
if (createFormArrayControl) {
181-
control.insert(i, createFormArrayControl(key as ArrayPropertyKey<FormInterface>, value[i]));
182-
} else {
183-
control.insert(i, new FormControl(value[i]));
184-
}
180+
control.insert(i, createFormArrayControl(key as ArrayPropertyKey<FormInterface>, value[i]));
185181
}
186182
});
187183
};

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

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { FormControl } from '@angular/forms';
12
import isEqual from 'fast-deep-equal';
23
import { getObservableLifecycle } from 'ngx-observable-lifecycle';
34
import { EMPTY, forkJoin, Observable, of, timer } from 'rxjs';
@@ -14,7 +15,13 @@ import {
1415
tap,
1516
withLatestFrom,
1617
} from 'rxjs/operators';
17-
import { isNullOrUndefined } from './shared/ngx-sub-form-utils';
18+
import {
19+
ArrayPropertyValue,
20+
isNullOrUndefined,
21+
OneOfControlsTypes,
22+
TypedAbstractControl,
23+
TypedFormControl,
24+
} from './shared/ngx-sub-form-utils';
1825
import {
1926
createFormDataFromOptions,
2027
getControlValueAccessorBindings,
@@ -25,6 +32,7 @@ import {
2532
import {
2633
ComponentHooks,
2734
ControlValueAccessorComponentInstance,
35+
CreateFormArrayControlMethod,
2836
FormBindings,
2937
FormType,
3038
NgxFormOptions,
@@ -36,8 +44,9 @@ import {
3644
} from './ngx-sub-form.types';
3745

3846
const optionsHaveInstructionsToCreateArrays = <ControlInterface, FormInterface>(
39-
options: NgxSubFormOptions<ControlInterface, FormInterface>,
40-
): options is NgxSubFormOptions<ControlInterface, FormInterface> & NgxSubFormArrayOptions<FormInterface> => true;
47+
options: NgxFormOptions<ControlInterface, FormInterface> & Partial<NgxSubFormArrayOptions<FormInterface>>,
48+
): options is NgxSubFormOptions<ControlInterface, FormInterface> & NgxSubFormArrayOptions<FormInterface> =>
49+
!!options.createFormArrayControl;
4150

4251
// @todo find a better name
4352
const isRoot = <ControlInterface, FormInterface>(
@@ -181,19 +190,18 @@ export function createForm<ControlInterface, FormInterface>(
181190
? lifecyleHooks.onDestroy.pipe(mapTo(null))
182191
: EMPTY;
183192

193+
const createFormArrayControl: Required<NgxSubFormArrayOptions<FormInterface>>['createFormArrayControl'] =
194+
optionsHaveInstructionsToCreateArrays<ControlInterface, FormInterface>(options) && options.createFormArrayControl
195+
? options.createFormArrayControl
196+
: (key, initialValue) => new FormControl(initialValue);
197+
184198
const sideEffects = {
185199
broadcastValueToParent$: registerOnChange$.pipe(
186200
switchMap(onChange => broadcastValueToParent$.pipe(tap(value => onChange(value)))),
187201
),
188202
applyUpstreamUpdateOnLocalForm$: transformedValue$.pipe(
189203
tap(value => {
190-
handleFormArrays<FormInterface>(
191-
formArrays,
192-
value,
193-
optionsHaveInstructionsToCreateArrays<ControlInterface, FormInterface>(options)
194-
? options.createFormArrayControl
195-
: null,
196-
);
204+
handleFormArrays<FormInterface>(formArrays, value, createFormArrayControl);
197205

198206
formGroup.reset(value, { emitEvent: false });
199207

@@ -241,7 +249,6 @@ export function createForm<ControlInterface, FormInterface>(
241249
get formGroupErrors() {
242250
return getFormGroupErrors<ControlInterface, FormInterface>(formGroup);
243251
},
244-
// todo
245-
createFormArrayControl: (options as any).createFormArrayControl,
252+
createFormArrayControl,
246253
};
247254
}

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Controls,
88
ControlsNames,
99
NewFormErrors,
10+
OneOfControlsTypes,
1011
TypedFormGroup,
1112
} from './shared/ngx-sub-form-utils';
1213
import { FormGroupOptions } from './shared/ngx-sub-form.types';
@@ -33,18 +34,20 @@ export interface NgxSubForm<FormInterface> {
3334
readonly formGroup: TypedFormGroup<FormInterface>;
3435
readonly formControlNames: ControlsNames<FormInterface>;
3536
readonly formGroupErrors: NewFormErrors<FormInterface>;
36-
readonly createFormArrayControl: any;
37+
readonly createFormArrayControl: CreateFormArrayControlMethod<FormInterface>;
3738
}
3839

40+
export type CreateFormArrayControlMethod<FormInterface> = <K extends ArrayPropertyKey<FormInterface>>(
41+
key: K,
42+
initialValue: ArrayPropertyValue<FormInterface, K>,
43+
) => FormControl;
44+
3945
export interface NgxRootForm<ControlInterface> extends NgxSubForm<ControlInterface> {
4046
// @todo: anything else needed here?
4147
}
4248

4349
export interface NgxSubFormArrayOptions<FormInterface> {
44-
createFormArrayControl?: (
45-
key: ArrayPropertyKey<FormInterface>,
46-
value: ArrayPropertyValue<FormInterface>,
47-
) => FormControl;
50+
createFormArrayControl?: CreateFormArrayControlMethod<FormInterface>;
4851
}
4952

5053
export interface NgxSubFormRemapOptions<ControlInterface, FormInterface> {

src/app/main-rewrite/listing/listing-form/vehicle-listing/crew-members/crew-members.component.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ export class CrewMembersComponent {
2727
fromFormGroup: (formValue: CrewMembersForm): CrewMember[] => {
2828
return formValue.crewMembers;
2929
},
30-
createFormArrayControl: (
31-
key: ArrayPropertyKey<CrewMembersForm> | undefined,
32-
value: ArrayPropertyValue<CrewMembersForm>,
33-
) => {
30+
createFormArrayControl: (key, value) => {
3431
switch (key) {
3532
case 'crewMembers':
3633
return new FormControl(value, [Validators.required]);

0 commit comments

Comments
 (0)