Skip to content

Commit

Permalink
fix: accept deep partials in patchValue and reset methods (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelss95 committed Nov 16, 2020
1 parent 1b7dc5d commit ee41c40
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 14 deletions.
10 changes: 7 additions & 3 deletions projects/ngneat/reactive-forms/src/lib/formArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import {
ValidatorOrOpts,
ControlValue,
AbstractControlOf,
ValidatorFn
ValidatorFn,
DeepPartial
} from './types';
import { coerceArray, mergeErrors, removeError } from './utils';

Expand Down Expand Up @@ -101,8 +102,11 @@ export class FormArray<T = any, E extends object = any> extends NgFormArray {
super.setValue(valueOrObservable, options);
}

patchValue(valueOrObservable: Observable<Partial<ControlValue<T>>[]>, options?: ControlEventOptions): Subscription;
patchValue(valueOrObservable: Partial<ControlValue<T>>[], options?: ControlEventOptions): void;
patchValue(
valueOrObservable: Observable<DeepPartial<ControlValue<T>>[]>,
options?: ControlEventOptions
): Subscription;
patchValue(valueOrObservable: DeepPartial<ControlValue<T>>[], options?: ControlEventOptions): void;
patchValue(valueOrObservable: any, options?: ControlEventOptions): Subscription | void {
if (isObservable(valueOrObservable)) {
return valueOrObservable.subscribe((value: T[]) => super.patchValue(value, options));
Expand Down
9 changes: 5 additions & 4 deletions projects/ngneat/reactive-forms/src/lib/formGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ import {
ControlsValue,
AbstractControlsOf,
PersistOptions,
ValidatorFn
ValidatorFn,
DeepPartial
} from './types';
import { coerceArray, mergeErrors, removeError, wrapIntoObservable } from './utils';
import { FormArray } from './formArray';
Expand Down Expand Up @@ -166,8 +167,8 @@ export class FormGroup<T extends Obj = any, E extends object = any> extends NgFo
super.setValue(valueOrObservable, options);
}

patchValue(valueOrObservable: Observable<Partial<ControlsValue<T>>>, options?: ControlEventOptions): Subscription;
patchValue(valueOrObservable: Partial<ControlsValue<T>>, options?: ControlEventOptions): void;
patchValue(valueOrObservable: Observable<DeepPartial<ControlsValue<T>>>, options?: ControlEventOptions): Subscription;
patchValue(valueOrObservable: DeepPartial<ControlsValue<T>>, options?: ControlEventOptions): void;
patchValue(valueOrObservable: any, options?: ControlEventOptions): Subscription | void {
if (isObservable(valueOrObservable)) {
return valueOrObservable.subscribe(value => super.patchValue(value, options));
Expand Down Expand Up @@ -217,7 +218,7 @@ export class FormGroup<T extends Obj = any, E extends object = any> extends NgFo
markAllDirty(this);
}

reset(formState?: Partial<ControlsValue<T>>, options?: ControlEventOptions): void {
reset(formState?: DeepPartial<ControlsValue<T>>, options?: ControlEventOptions): void {
super.reset(formState, options);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { expectTypeOf } from 'expect-type';
import {
Observable,
of,
Subscription
} from 'rxjs';
import { Observable, of, Subscription } from 'rxjs';
import { FormArray } from '../formArray';
import { FormControl } from '../formControl';
import { FormGroup } from '../formGroup';
Expand Down Expand Up @@ -33,7 +29,7 @@ test('control value should be of type User[]', () => {
test('control value should be constructed according to generic control type', () => {
const control = new FormArray<FormGroup<NestedFormControls>>([]);
expectTypeOf<NestedForm[]>(control.value).toEqualTypeOf([nestedFormValue]);
})
});

test('control valueChanges$ should be of type stream of User[]', () => {
const control = new FormArray<User>([]);
Expand Down Expand Up @@ -72,6 +68,11 @@ test('control patchValue should accept value of type User[] or stream of User[]'
expectTypeOf(control.patchValue(of([user]))).toEqualTypeOf(new Subscription());
});

test('control patchValue should accept nested partials', () => {
const control = new FormArray<NestedForm>([]);
expectTypeOf(control.patchValue(of([{ b: { c: [2] } }]))).toEqualTypeOf(new Subscription());
});

test('control disableWhile should return subscription', () => {
const control = new FormArray<User>([]);
expectTypeOf(control.disabledWhile).returns.not.toBeAny();
Expand Down Expand Up @@ -195,5 +196,5 @@ test('should be able to set value to control inside group', () => {
.at(0)
.get('id')
.setValue(3);
expectTypeOf((control.at(0)).getControl('id').value).toBeNumber();
expectTypeOf(control.at(0).getControl('id').value).toBeNumber();
});
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,18 @@ describe('with generic', () => {
control.setValidators([required, pattern]);
});

test('control patchValue should accept nested partials', () => {
const control = new FormGroup<NestedForm>({
a: new FormControl(22),
b: new FormControl({
a: '',
c: [3]
}),
d: new FormControl<boolean>()
});
expectTypeOf(control.patchValue(of({ b: { c: [4] } }))).toEqualTypeOf(new Subscription());
});

test('should be able to set async validators', () => {
const control = new FormGroup<User, Errors>(null);
control.setAsyncValidators([requiredAsync, patternAsync]);
Expand Down
3 changes: 3 additions & 0 deletions projects/ngneat/reactive-forms/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ export interface NgValidatorsErrors {

export type BoxedValue<T> = { value: T; disabled?: boolean };
export type OrBoxedValue<T> = T | BoxedValue<T>;
export type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};

export type Obj = { [key: string]: any };
type ArrayType<T> = T extends Array<infer R> ? R : any;
Expand Down

0 comments on commit ee41c40

Please sign in to comment.