Skip to content

Commit

Permalink
feat(core): allow onInit/afterView/afterContent to return observables (
Browse files Browse the repository at this point in the history
  • Loading branch information
aitboudad committed May 21, 2020
1 parent a53a737 commit f91637e
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { Component, OnDestroy } from '@angular/core';
import { Component } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormlyFormOptions, FormlyFieldConfig } from '@ngx-formly/core';
import { Subject } from 'rxjs';
import { takeUntil, startWith, tap, filter } from 'rxjs/operators';
import { startWith, tap, filter } from 'rxjs/operators';

@Component({
selector: 'formly-app-example',
templateUrl: './app.component.html',
})
export class AppComponent implements OnDestroy {
onDestroy$ = new Subject<void>();
export class AppComponent {
form = new FormGroup({});
model = {
investmentsCount: 3,
Expand All @@ -26,11 +24,11 @@ export class AppComponent implements OnDestroy {
type: 'number',
label: 'Investments count',
required: true,
min: 1,
},
hooks: {
onInit: (field) => {
field.formControl.valueChanges.pipe(
takeUntil(this.onDestroy$),
return field.formControl.valueChanges.pipe(
startWith(field.formControl.value),
filter(v => v > 0),
tap(value => {
Expand All @@ -40,7 +38,7 @@ export class AppComponent implements OnDestroy {
investmentsCount: value,
};
}),
).subscribe();
);
},
},
},
Expand All @@ -61,9 +59,4 @@ export class AppComponent implements OnDestroy {
submit() {
alert(JSON.stringify(this.model));
}

ngOnDestroy(): void {
this.onDestroy$.next();
this.onDestroy$.complete();
}
}
37 changes: 36 additions & 1 deletion src/core/src/lib/components/formly.field.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TestBed, ComponentFixture, TestBedStatic } from '@angular/core/testing';
import { timer } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { map, shareReplay, tap } from 'rxjs/operators';
import { createGenericTestComponent } from '../test-utils';

import { ChangeDetectionStrategy, Component } from '@angular/core';
Expand Down Expand Up @@ -190,6 +190,41 @@ describe('FormlyField Component', () => {
expect(hooks.onDestroy).toHaveBeenCalledWith(testComponentInputs.field);
});

it('init hooks with observables', () => {
const control = new FormControl();
const spy = jasmine.createSpy('valueChanges spy');
const initHookFn = (f: FormlyFieldConfig) => {
return f.formControl.valueChanges.pipe(tap(spy));
};

testComponentInputs = {
field: {
key: 'title',
type: 'text',
formControl: control,
parent: {
formControl: new FormGroup({}),
},
hooks: {
afterContentInit: initHookFn,
afterViewInit: initHookFn,
onInit: initHookFn,
},
},
};

const fixture = createTestComponent('<formly-field [field]="field"></formly-field>');
expect(spy).not.toHaveBeenCalled();

control.patchValue('test');
expect(spy).toHaveBeenCalledTimes(3);

spy.calls.reset();
fixture.destroy();
control.patchValue('test');
expect(spy).not.toHaveBeenCalled();
});

it('should support async render field type', () => {
testComponentInputs = {
field: {
Expand Down
9 changes: 8 additions & 1 deletion src/core/src/lib/components/formly.field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { FormlyFieldConfig, FormlyFormOptions, FormlyFieldConfigCache } from './
import { defineHiddenProp, wrapProperty } from '../utils';
import { FieldWrapper } from '../templates/field.wrapper';
import { FieldType } from '../templates/field.type';
import { isObservable } from 'rxjs';

@Component({
selector: 'formly-field',
Expand Down Expand Up @@ -36,6 +37,7 @@ export class FormlyField implements OnInit, OnChanges, DoCheck, AfterContentInit
@ViewChild('container', <any> {read: ViewContainerRef, static: true }) containerRef: ViewContainerRef;
private hostObservers: Function[] = [];
private componentRefs: any[] = [];
private hooksObservers: Function[] = [];

constructor(
private formlyConfig: FormlyConfig,
Expand Down Expand Up @@ -79,6 +81,7 @@ export class FormlyField implements OnInit, OnChanges, DoCheck, AfterContentInit
ngOnDestroy() {
this.resetRefs(this.field);
this.hostObservers.forEach(unsubscribe => unsubscribe());
this.hooksObservers.forEach(unsubscribe => unsubscribe());
this.triggerHook('onDestroy');
}

Expand Down Expand Up @@ -116,7 +119,11 @@ export class FormlyField implements OnInit, OnChanges, DoCheck, AfterContentInit
private triggerHook(name: string, changes?: SimpleChanges) {
if (this.field && this.field.hooks && this.field.hooks[name]) {
if (!changes || changes.field) {
this.field.hooks[name](this.field);
const r = this.field.hooks[name](this.field);
if (isObservable(r) && ['onInit', 'afterContentInit', 'afterViewInit'].indexOf(name) !== -1) {
const sub = r.subscribe();
this.hooksObservers.push(() => sub.unsubscribe());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ export class FieldExpressionExtension implements FormlyExtension {
let subscription: Subscription = subscribe();
const onInit = field.hooks.onInit;
field.hooks.onInit = () => {
onInit && onInit(field);
if (subscription === null) {
subscription = subscribe();
}
return onInit && onInit(field);
};

const onDestroy = field.hooks.onDestroy;
Expand Down

0 comments on commit f91637e

Please sign in to comment.