diff --git a/README.md b/README.md index 69ab2bc5..5a0b132d 100644 --- a/README.md +++ b/README.md @@ -538,7 +538,6 @@ export class CrewMemberComponent extends NgxSubFormComponent { **Hooks** -- `onFormUpdate`: Allows you to react whenever the form is being modified. Instead of subscribing to `this.formGroup.valueChanges` or `this.formControls.someProp.valueChanges` you will not have to deal with anything asynchronous nor have to worry about subscriptions and memory leaks. Just implement the method `onFormUpdate(formUpdate: FormUpdate): void` and if you need to know which property changed do a check like the following: `if (formUpdate.yourProperty) {}`. Be aware that this method will be called only when there are either local changes to the form or changes coming from subforms. If the parent `setValue` or `patchValue` this method won't be triggered - `getFormGroupControlOptions`: Allows you to define control options for construction of the internal FormGroup. Use this to define form-level validators - `createFormArrayControl`: Allows you to create the `FormControl` of a given property of your form (to define validators for example). When you want to use this hook, implement the following interface `NgxFormWithArrayControls` - `handleEmissionRate`: Allows you to define a custom emission rate (top level or any sub level) diff --git a/projects/ngx-sub-form/src/lib/ngx-sub-form.component.spec.ts b/projects/ngx-sub-form/src/lib/ngx-sub-form.component.spec.ts index 44b5bce9..eecb8be4 100644 --- a/projects/ngx-sub-form/src/lib/ngx-sub-form.component.spec.ts +++ b/projects/ngx-sub-form/src/lib/ngx-sub-form.component.spec.ts @@ -388,63 +388,6 @@ describe(`NgxSubFormComponent`, () => { }); }); - describe(`onFormUpdate`, () => { - it(`should not call onFormUpdate when patched by the parent (through "writeValue")`, (done: () => void) => { - const spyOnFormUpdate = jasmine.createSpy(); - subComponent.onFormUpdate = spyOnFormUpdate; - subComponent.registerOnChange(() => {}); - - setTimeout(() => { - spyOnFormUpdate.calls.reset(); - - subComponent.writeValue({ ...subComponent.formGroupValues, color: 'red' }); - - setTimeout(() => { - expect(spyOnFormUpdate).not.toHaveBeenCalled(); - - done(); - }, 0); - }, 0); - }); - - it(`should call onFormUpdate everytime the form changes (local changes)`, (done: () => void) => { - const spyOnFormUpdate = jasmine.createSpy(); - subComponent.onFormUpdate = spyOnFormUpdate; - subComponent.registerOnChange(() => {}); - - subComponent.formGroupControls.color.setValue(`red`); - - setTimeout(() => { - expect(spyOnFormUpdate).toHaveBeenCalledWith({ - color: true, - }); - - done(); - }, 0); - }); - - it(`should correctly emit the onChange value only once when form is patched locally`, (done: () => void) => { - const spyOnFormUpdate = jasmine.createSpy(); - const spyOnChange = jasmine.createSpy(); - subComponent.onFormUpdate = spyOnFormUpdate; - subComponent.registerOnChange(spyOnChange); - (subComponent as any).emitInitialValueOnInit = false; - - subComponent.formGroup.patchValue({ color: 'red', canFire: false }); - - setTimeout(() => { - expect(spyOnFormUpdate).toHaveBeenCalledWith({ - canFire: true, - }); - - expect(spyOnChange).toHaveBeenCalledTimes(1); - expect(spyOnChange).toHaveBeenCalledWith({ color: 'red', canFire: false, crewMemberCount: 10 }); - - done(); - }, 0); - }); - }); - describe('getFormGroupControlOptions', () => { interface Numbered { numberOne: number; diff --git a/projects/ngx-sub-form/src/lib/ngx-sub-form.component.ts b/projects/ngx-sub-form/src/lib/ngx-sub-form.component.ts index 59855219..81a44395 100644 --- a/projects/ngx-sub-form/src/lib/ngx-sub-form.component.ts +++ b/projects/ngx-sub-form/src/lib/ngx-sub-form.component.ts @@ -22,7 +22,7 @@ import { ControlsType, ArrayPropertyKey, } from './ngx-sub-form-utils'; -import { FormGroupOptions, NgxFormWithArrayControls, OnFormUpdate, TypedFormGroup } from './ngx-sub-form.types'; +import { FormGroupOptions, NgxFormWithArrayControls, TypedFormGroup } from './ngx-sub-form.types'; type MapControlFunction = (ctrl: AbstractControl, key: keyof FormInterface) => MapValue; type FilterControlFunction = ( @@ -32,7 +32,7 @@ type FilterControlFunction = ( ) => boolean; export abstract class NgxSubFormComponent - implements ControlValueAccessor, Validator, OnDestroy, OnFormUpdate { + implements ControlValueAccessor, Validator, OnDestroy { public get formGroupControls(): ControlsType { // @note form-group-undefined we need the return null here because we do not want to expose the fact that // the form can be undefined, it's handled internally to contain an Angular bug @@ -170,8 +170,6 @@ export abstract class NgxSubFormComponent): void {} - /** * Extend this method to provide custom local FormGroup level validation */ @@ -348,17 +346,6 @@ export abstract class NgxSubFormComponent[] = formControlNames.map(key => - this.formGroup.controls[key].valueChanges.pipe( - startWith(this.formGroup.controls[key].value), - map(value => ({ key, value })), - ), - ); - - const lastKeyEmitted$: Observable = merge(...formValues.map(obs => obs.pipe(map(x => x.key)))); - this.subscription = this.formGroup.valueChanges .pipe( // hook to give access to the observable for sub-classes @@ -370,9 +357,7 @@ export abstract class NgxSubFormComponent !!this.formGroup), - // detect which stream emitted last - withLatestFrom(lastKeyEmitted$), - map(([_, keyLastEmit], index) => { + map((_, index) => { if (index > 0 && this.onTouched) { this.onTouched(); } @@ -390,10 +375,6 @@ export abstract class NgxSubFormComponent = {}; - formUpdate[keyLastEmit] = true; - this.onFormUpdate(formUpdate); } }), ) diff --git a/projects/ngx-sub-form/src/lib/ngx-sub-form.types.ts b/projects/ngx-sub-form/src/lib/ngx-sub-form.types.ts index 71f4b967..41348285 100644 --- a/projects/ngx-sub-form/src/lib/ngx-sub-form.types.ts +++ b/projects/ngx-sub-form/src/lib/ngx-sub-form.types.ts @@ -2,10 +2,6 @@ import { FormControl, FormGroup, ValidationErrors } from '@angular/forms'; import { Observable } from 'rxjs'; import { ArrayPropertyKey, ArrayPropertyValue, Controls, FormUpdate } from './ngx-sub-form-utils'; -export interface OnFormUpdate { - onFormUpdate?: (formUpdate: FormUpdate) => void; -} - type Omit = Pick>; type Nullable = T | null;