Skip to content
This repository has been archived by the owner on Aug 25, 2020. It is now read-only.

Commit

Permalink
feat: fields service replaces with provider
Browse files Browse the repository at this point in the history
BREAKING CHANGE: custom fields now injected using forRoot
  • Loading branch information
artemnih committed Jan 22, 2019
1 parent 8e01865 commit 6d1ed3c
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 97 deletions.
2 changes: 1 addition & 1 deletion dist/ngx-forms.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export { FieldConfig, Field } from "./src/app/types";
export { NgxFormModule } from "./src/app";
export { DynamicFieldService } from "./src/app/services/dynamic-field.service";
export { DynamicFormComponent } from "./src/app/containers/dynamic-form/dynamic-form.component";
44 changes: 28 additions & 16 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
import { NgModule, NO_ERRORS_SCHEMA, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { QuillModule } from 'ngx-quill';
Expand All @@ -8,7 +8,6 @@ import { DynamicPanelComponent } from './app/containers/dynamic-panel/dynamic-pa
import { FormNavModule } from './nav/nav-app';
import { TagInputModule } from 'ngx-chips';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { DynamicFieldService } from './app/services/dynamic-field.service';
import { FormInputComponent } from './app/components/form-input/form-input.component';
import { FormSelectComponent } from './app/components/form-select/form-select.component';
import { FormTextEditorComponent } from './app/components/form-text-editor/form-text-editor.component';
Expand All @@ -17,6 +16,18 @@ import { FormRadioComponent } from './app/components/form-radio/form-radio.compo
import { FormTextareaComponent } from './app/components/form-textarea/form-textarea.component';
import { FormInputHiddenComponent } from './app/components/form-hidden/form-hidden.component';
import { FormLabelComponent } from './app/components/form-label/form-label.component';
import { FIELD_DICT_TOKEN, FieldDictionary } from './app/types';

const defaultInputs: FieldDictionary = {
text: FormInputComponent,
select: FormSelectComponent,
editor: FormTextEditorComponent,
textarea: FormTextareaComponent,
hidden: FormInputHiddenComponent,
radio: FormRadioComponent,
checkbox: FormCheckboxComponent,
label: FormLabelComponent
};

@NgModule({
imports: [
Expand Down Expand Up @@ -56,25 +67,26 @@ import { FormLabelComponent } from './app/components/form-label/form-label.compo
FormLabelComponent
],
providers: [
DynamicFieldService
{
provide: FIELD_DICT_TOKEN,
useValue: defaultInputs
}
],
schemas: [
NO_ERRORS_SCHEMA
]
})
export class NgxFormModule {

constructor(private dynamicFieldService: DynamicFieldService) {
this.dynamicFieldService.addField('text', FormInputComponent);
this.dynamicFieldService.addField('select', FormSelectComponent);
this.dynamicFieldService.addField('editor', FormTextEditorComponent);
this.dynamicFieldService.addField('textarea', FormTextareaComponent);
this.dynamicFieldService.addField('hidden', FormInputHiddenComponent);
this.dynamicFieldService.addField('radio', FormRadioComponent);
this.dynamicFieldService.addField('checkbox', FormCheckboxComponent);
this.dynamicFieldService.addField('label', FormLabelComponent);
public static forRoot(dictionary: FieldDictionary): ModuleWithProviders {
Object.keys(dictionary).forEach(key => defaultInputs[key] = dictionary[key]);
return {
ngModule: NgxFormModule,
providers: [
{
provide: FIELD_DICT_TOKEN,
useValue: defaultInputs
}
]
};
}

}

export { DynamicFieldService };
23 changes: 11 additions & 12 deletions src/app/components/dynamic-field/dynamic-field.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { FormsModule, ReactiveFormsModule, FormGroup, FormBuilder, FormControl } from '@angular/forms';
import { ComponentFixture, TestBed, getTestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DynamicFieldDirective } from "./dynamic-field.directive"
import { By } from '@angular/platform-browser';
import { FieldConfig } from "../../types"
import { DynamicFieldService } from "../../services/dynamic-field.service";
import { FieldConfig, FieldDictionary, FIELD_DICT_TOKEN } from "../../types";
import { FormInputComponent } from "../form-input/form-input.component";
import {FormInputHiddenComponent} from '../form-hidden/form-hidden.component';
import { FormInputHiddenComponent } from '../form-hidden/form-hidden.component';

const defaultInputs: FieldDictionary = {
text: FormInputComponent,
hidden: FormInputHiddenComponent
}

@Component({
template: `<form [formGroup]="form"><div dynamicField [field]="field" [group]="form"></div></form>`
Expand Down Expand Up @@ -38,14 +42,9 @@ describe('DynamicFieldDirective', () => {
TestBed.configureTestingModule({
declarations: [DynamicFieldDirective, TestComponent],
imports: [FormsModule, ReactiveFormsModule, TestModule],
providers: [DynamicFieldService]
providers: [{ provide: FIELD_DICT_TOKEN, useValue: defaultInputs }]
});

const injector = getTestBed();
const service:DynamicFieldService = injector.get(DynamicFieldService);
service.addField('text', FormInputComponent);
service.addField('hidden', FormInputHiddenComponent);

fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
component.field = { "type": "text", "label": "Title", "name": "publicationTitle", "placeholder": "Please enter", "required": true };
Expand Down Expand Up @@ -157,7 +156,7 @@ describe('TestNoGroup', () => {
TestBed.configureTestingModule({
declarations: [DynamicFieldDirective, TestNoGroup],
imports: [FormsModule, ReactiveFormsModule, TestModule],
providers: [DynamicFieldService]
providers: [{ provide: FIELD_DICT_TOKEN, useValue: defaultInputs }]
});
TestBed.createComponent(TestNoGroup);
});
Expand All @@ -177,7 +176,7 @@ describe('TestNoInput', () => {
TestBed.configureTestingModule({
declarations: [DynamicFieldDirective, TestNoInput],
imports: [FormsModule, ReactiveFormsModule, TestModule],
providers: [DynamicFieldService]
providers: [{ provide: FIELD_DICT_TOKEN, useValue: defaultInputs }]
});

fixture = TestBed.createComponent(TestNoInput);
Expand Down
9 changes: 4 additions & 5 deletions src/app/components/dynamic-field/dynamic-field.directive.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { ComponentRef, Directive, Input, OnInit, ViewContainerRef, ComponentFactoryResolver, OnDestroy } from '@angular/core';
import { ComponentRef, Directive, Input, OnInit, ViewContainerRef, ComponentFactoryResolver, OnDestroy, Inject } from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { Field } from '../../types';
import { Field, Type, FieldDictionary, FIELD_DICT_TOKEN } from '../../types';
import { FieldConfig } from '../../types';
import { DynamicFieldService } from '../../services/dynamic-field.service';

@Directive({
selector: '[dynamicField]'
Expand All @@ -16,16 +15,16 @@ export class DynamicFieldDirective implements Field, OnInit, OnDestroy {
constructor(
private resolver: ComponentFactoryResolver,
private container: ViewContainerRef,
private dynamicFieldService: DynamicFieldService,
private fb: FormBuilder,
@Inject(FIELD_DICT_TOKEN) private inputs: FieldDictionary
) { }

ngOnInit() {
if (!this.group) {
throw new Error('group is not set');
}

const componentReference = this.dynamicFieldService.getField(this.field.type);
const componentReference = this.inputs[this.field.type];
const component = this.resolver.resolveComponentFactory<Field>(componentReference);
this.component = this.container.createComponent(component);
this.component.instance.field = this.field;
Expand Down
24 changes: 9 additions & 15 deletions src/app/containers/dynamic-form/dynamic-form.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { DynamicFieldDirective } from '../../components/dynamic-field/dynamic-fi
import { Component, NgModule } from "@angular/core";
import { DynamicFormComponent, ConditionType } from "./dynamic-form.component";
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { DynamicFieldService } from "../../services/dynamic-field.service";
import { FormInputComponent } from '../../components/form-input/form-input.component';
import { CommonModule } from '@angular/common';
import { FormSelectComponent } from '../../components/form-select/form-select.component';
import { FormInputHiddenComponent } from '../../components/form-hidden/form-hidden.component';
import { By } from '@angular/platform-browser';
import { FormNavModule } from '../../../nav/nav-app';
import { FieldDictionary, FIELD_DICT_TOKEN } from '../../types';

interface IFormConfig {
form: any;
Expand All @@ -24,6 +24,12 @@ interface IDynamicForm {
lookups: any
}

const defaultInputs: FieldDictionary = {
text: FormInputComponent,
select: FormSelectComponent,
hidden: FormInputHiddenComponent
}

@Component({
template: `<dynamic-form [formConfig]="formConfig" #form="dynamicForm" [model]="data" [lookups]="lookups"></dynamic-form>`
})
Expand All @@ -50,18 +56,12 @@ describe('DynamicFormComponent', () => {
TestBed.configureTestingModule({
declarations: [DynamicFieldDirective, TestComponent, DynamicFormComponent, DynamicPanelComponent],
imports: [FormsModule, ReactiveFormsModule, TestModule, FormNavModule],
providers: [DynamicFieldService]
providers: [{ provide: FIELD_DICT_TOKEN, useValue: defaultInputs }]
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(TestComponent);

const injector = getTestBed();
const service: DynamicFieldService = injector.get(DynamicFieldService);
service.addField('text', FormInputComponent);
service.addField('hidden', FormInputHiddenComponent);
service.addField('select', FormSelectComponent);

component = fixture.componentInstance;
component.formConfig = {
form: [{
Expand Down Expand Up @@ -116,14 +116,8 @@ describe('DynamicFormComponent Core', () => {
TestBed.configureTestingModule({
declarations: [DynamicFieldDirective, TestComponent, DynamicFormComponent, DynamicPanelComponent],
imports: [FormsModule, ReactiveFormsModule, TestModule, FormNavModule],
providers: [DynamicFieldService]
providers: [{ provide: FIELD_DICT_TOKEN, useValue: defaultInputs }]
}).compileComponents();

const injector = getTestBed();
const service: DynamicFieldService = injector.get(DynamicFieldService);
service.addField('text', FormInputComponent);
service.addField('hidden', FormInputHiddenComponent);

});

beforeEach(() => {
Expand Down
14 changes: 10 additions & 4 deletions src/app/containers/dynamic-panel/dynamic-panel.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DynamicFieldDirective } from "../../components/dynamic-field/dynamic-field.directive";
import { DebugElement } from "@angular/core";
import { DynamicPanelComponent } from './dynamic-panel.component';
import { ReactiveFormsModule, FormsModule, FormBuilder, FormGroup } from '@angular/forms';
import { DynamicFieldService } from "../../services/dynamic-field.service";
import { ReactiveFormsModule, FormsModule, FormGroup } from '@angular/forms';
import { FIELD_DICT_TOKEN, FieldDictionary } from '../../types';
import { FormInputComponent } from '../../components/form-input/form-input.component';
import { FormInputHiddenComponent } from '../../components/form-hidden/form-hidden.component';

const defaultInputs: FieldDictionary = {
text: FormInputComponent,
hidden: FormInputHiddenComponent
}

describe('DynamicPanelComponent', () => {
let component: DynamicPanelComponent;
Expand Down Expand Up @@ -39,7 +45,7 @@ describe('DynamicPanelComponent', () => {
ReactiveFormsModule
],
declarations: [DynamicPanelComponent, DynamicFieldDirective],
providers: [DynamicFieldService]
providers: [ { provide: FIELD_DICT_TOKEN, useValue: defaultInputs }]
})
.compileComponents();
}));
Expand Down
20 changes: 0 additions & 20 deletions src/app/services/dynamic-field.service.spec.ts

This file was deleted.

23 changes: 0 additions & 23 deletions src/app/services/dynamic-field.service.ts

This file was deleted.

7 changes: 7 additions & 0 deletions src/app/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FormGroup } from '@angular/forms';
import { FieldConfig } from './types';
import { InjectionToken } from '@angular/core';

export interface ILookup {
name: string; // Name of lookup from lookup payload
Expand Down Expand Up @@ -32,3 +33,9 @@ export interface Field {
group: FormGroup;
model?: Object;
}

export type Type<T> = new (...args: any[]) => T;

export interface FieldDictionary { [key: string]: Type<Field>; }

export const FIELD_DICT_TOKEN = new InjectionToken<FieldDictionary>('fields');

0 comments on commit 6d1ed3c

Please sign in to comment.