diff --git a/README.md b/README.md index 282107a39..b97e3318d 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Explore the [**live sample**](http://ng2-dynamic-forms.udos86.de/sample/index.ht - [Form Control Configuration](#form-control-configuration) - [Form Control Events](#form-control-events) - [Updating Form Controls](#updating-form-controls) +- [Dynamic Option and List Population](#dynamic-form-control-option-and-list-population) - [Custom Templates](#custom-templates) - [Custom Validators](#custom-validators) - [Custom Form Controls](#custom-form-controls) @@ -689,6 +690,123 @@ To optimize this you can optionally pass a `DynamicFormComponent` to `detectChan this.formService.detectChanges(this.formComponent); ``` +## Dynamic Option And List Population +A common use case of more complex forms is having select, datalist, checkboxes and radio buttons automatically populate based on another form controls value. NG Dynamic Forms accomplishes this by allowing you to provide a `service`, per form control, which will get invoked when the related form controls value changes. + +### Configuration +To connect a form control one will need to include the `dataProvider` attribute along with a `relation` and `service`. See the definitions below. + +| Name | Description | +| :--- | :--- | +| relation | Similar to how relations work, you provide a rootPath or id to the related control | +| *relation*.id | ID of the input control | +| *relation*.rootPath | The path to the input control from the form group. | +| service | A token representing the service in the DI. | + +```typescript +export function WikiPageForm(): DynamicFormControlModel[] { + return [ + new DynamicInputModel({ + id: 'wiki-title', + label: 'Search Title', + value: '', + validators: { + required: null, + }, + errorMessages: { + required: '{{ label }} is required', + }, + }), + new DynamicSelectModel({ + id: 'wiki-page', + label: 'Wiki Page', + value: '-1', + options: [{value: '-1', label: '-- select a wikipedia page'}], + dataProvider: { + relation: {id: 'wiki-title'}, + service: WikipediaService, + }, + relations: [ + { + match: MATCH_DISABLED, + when: [ + { + rootPath: 'wiki-title', value: '', + }, + ], + }, + ], + validators: { + required: null, + }, + errorMessages: { + required: '{{ label }} is required', + }, + }) + ]; +} +``` +### Data Provider +NG Dynamic forms will look attempt to inject a given service via the token provided by the `dataProvider.service` definition. Your service must implement one of two methods depending on your form control. + +| Control Name | Interface | +| :--- | :--- | +| DynamicInputModel | DynamicFormControlListDataProvider\ | +| DynamicSelectModel | DynamicFormControlOptionDataProvider\ | +| DynamicSelectModel | DynamicFormControlOptionDataProvider\ | +| DynamicRadioModel | DynamicFormControlOptionDataProvider\ | +| DynamicCheckboxModel | DynamicFormControlOptionDataProvider\ | + +```typescript +const WIKI_URL = 'https://en.wikipedia.org/w/api.php'; +const PARAMS = new HttpParams({ + fromObject: { + action: 'opensearch', + format: 'json', + origin: '*', + }, +}); + +@Injectable({ + providedIn: 'root', +}) +export class WikipediaService + implements DynamicFormControlListDataProvider, DynamicFormControlOptionDataProvider { + constructor(private http: HttpClient) {} + + fetchList(value: string): Observable { + return this.fetch(value); + } + + fetchOptions(value: string): Observable[]> { + return this.fetch(value).pipe(map( + response => { + if (!Array.isArray(response)) { + return []; + } + + return response.map((val) => { + return { + label: val, + value: val as string, + } as DynamicFormOptionConfig; + }); + }), + ); + } + + fetch(term: string): Observable { + if (typeof(term) !== 'string' || term === '') { + return of([]); + } + + return this.http + .get(WIKI_URL, {params: PARAMS.set('search', term)}).pipe( + map(response => response[1]), + ); + } +} +``` ## Custom Templates diff --git a/projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-control-container.component.ts b/projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-control-container.component.ts index 921b6148e..06ba9af9e 100644 --- a/projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-control-container.component.ts @@ -44,6 +44,7 @@ import { isString } from "../utils/core.utils"; import { DynamicFormRelationService } from "../service/dynamic-form-relation.service"; import { DynamicFormGroupComponent } from "./dynamic-form-group.component"; import { DynamicFormArrayComponent } from "./dynamic-form-array.component"; +import { DynamicFormDataService } from '../service/dynamic-form-data.service'; export abstract class DynamicFormControlContainerComponent implements OnChanges, OnDestroy { @@ -77,7 +78,8 @@ export abstract class DynamicFormControlContainerComponent implements OnChanges, protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { } ngOnChanges(changes: SimpleChanges) { @@ -287,6 +289,10 @@ export abstract class DynamicFormControlContainerComponent implements OnChanges, this.subscriptions.push(...this.relationService.subscribeRelations(this.model, this.group, this.control)); } + + if (this.model.dataProvider) { + this.subscriptions.push(this.dataService.connectDynamicFormControls(this.model, this.group)); + } } } diff --git a/projects/ng-dynamic-forms/core/src/lib/core.module.ts b/projects/ng-dynamic-forms/core/src/lib/core.module.ts index f8167a6c5..4930951ee 100644 --- a/projects/ng-dynamic-forms/core/src/lib/core.module.ts +++ b/projects/ng-dynamic-forms/core/src/lib/core.module.ts @@ -8,6 +8,7 @@ import { DynamicFormLayoutService } from "./service/dynamic-form-layout.service" import { DynamicFormValidationService } from "./service/dynamic-form-validation.service"; import { DynamicFormComponentService } from "./service/dynamic-form-component.service"; import { DynamicFormRelationService } from "./service/dynamic-form-relation.service"; +import { DynamicFormDataService } from './service/dynamic-form-data.service'; @NgModule({ imports: [ @@ -35,7 +36,8 @@ export class DynamicFormsCoreModule { DynamicFormLayoutService, DynamicFormValidationService, DynamicFormComponentService, - DynamicFormRelationService + DynamicFormRelationService, + DynamicFormDataService, ] }; } diff --git a/projects/ng-dynamic-forms/core/src/lib/core.ts b/projects/ng-dynamic-forms/core/src/lib/core.ts index c214a83ca..be0172656 100644 --- a/projects/ng-dynamic-forms/core/src/lib/core.ts +++ b/projects/ng-dynamic-forms/core/src/lib/core.ts @@ -39,6 +39,7 @@ export * from "./model/switch/dynamic-switch.model"; export * from "./model/textarea/dynamic-textarea.model"; export * from "./model/timepicker/dynamic-timepicker.model"; +export * from "./model/misc/dynamic-form-control-data.model"; export * from "./model/misc/dynamic-form-control-layout.model"; export * from "./model/misc/dynamic-form-control-path.model"; export * from "./model/misc/dynamic-form-control-relation.model"; @@ -50,6 +51,7 @@ export * from "./service/dynamic-form-validators"; export * from "./service/dynamic-form.service"; export * from "./service/dynamic-form-component.service"; +export * from "./service/dynamic-form-data.service"; export * from "./service/dynamic-form-layout.service"; export * from "./service/dynamic-form-relation.service"; export * from "./service/dynamic-form-validation.service"; diff --git a/projects/ng-dynamic-forms/core/src/lib/model/dynamic-form-control.model.ts b/projects/ng-dynamic-forms/core/src/lib/model/dynamic-form-control.model.ts index 3433b31e3..2eac91db1 100644 --- a/projects/ng-dynamic-forms/core/src/lib/model/dynamic-form-control.model.ts +++ b/projects/ng-dynamic-forms/core/src/lib/model/dynamic-form-control.model.ts @@ -5,6 +5,7 @@ import { DynamicFormControlRelation } from "./misc/dynamic-form-control-relation import { DynamicFormHook, DynamicValidatorsConfig } from "./misc/dynamic-form-control-validation.model"; import { serializable, serialize } from "../decorator/serializable.decorator"; import { isBoolean, isObject, isString } from "../utils/core.utils"; +import {DynamicFormControlDataConfig} from './misc/dynamic-form-control-data.model'; export interface DynamicFormControlModelConfig { @@ -20,6 +21,7 @@ export interface DynamicFormControlModelConfig { relations?: DynamicFormControlRelation[]; updateOn?: DynamicFormHook; validators?: DynamicValidatorsConfig; + dataProvider?: DynamicFormControlDataConfig; } export abstract class DynamicFormControlModel implements DynamicPathable { @@ -38,6 +40,7 @@ export abstract class DynamicFormControlModel implements DynamicPathable { @serializable() relations: DynamicFormControlRelation[]; @serializable() updateOn: DynamicFormHook | null; @serializable() validators: DynamicValidatorsConfig | null; + @serializable() dataProvider: DynamicFormControlDataConfig | null; private readonly disabled$: BehaviorSubject; @@ -63,6 +66,7 @@ export abstract class DynamicFormControlModel implements DynamicPathable { this.disabled$ = new BehaviorSubject(isBoolean(config.disabled) ? config.disabled : false); this.disabled$.subscribe(disabled => this._disabled = disabled); this.disabledChanges = this.disabled$.asObservable(); + this.dataProvider = config.dataProvider || null; } get disabled(): boolean { diff --git a/projects/ng-dynamic-forms/core/src/lib/model/misc/dynamic-form-control-data.model.ts b/projects/ng-dynamic-forms/core/src/lib/model/misc/dynamic-form-control-data.model.ts new file mode 100644 index 000000000..737759782 --- /dev/null +++ b/projects/ng-dynamic-forms/core/src/lib/model/misc/dynamic-form-control-data.model.ts @@ -0,0 +1,20 @@ +import {Observable} from 'rxjs'; +import {DynamicFormOptionConfig} from '../dynamic-option-control.model'; + +export interface DynamicFormControlDataRelation { + rootPath?: string; + id?: string; +} + +export interface DynamicFormControlDataConfig { + relation: DynamicFormControlDataRelation; + service: any; +} + +export interface DynamicFormControlListDataProvider { + fetchList(value: string): Observable; +} + +export interface DynamicFormControlOptionDataProvider { + fetchOptions(value: string): Observable[]>; +} diff --git a/projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-data.service.spec.ts b/projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-data.service.spec.ts new file mode 100644 index 000000000..662baf4a1 --- /dev/null +++ b/projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-data.service.spec.ts @@ -0,0 +1,220 @@ +import {TestBed, inject, tick, fakeAsync} from "@angular/core/testing"; +import {FormGroup, ReactiveFormsModule} from "@angular/forms"; +import { DynamicFormService } from "./dynamic-form.service"; +import { DynamicSelectModel } from "../model/select/dynamic-select.model"; +import { DynamicRadioGroupModel } from "../model/radio/dynamic-radio-group.model"; +import {DynamicFormDataService} from './dynamic-form-data.service'; +import { + DynamicFormControlListDataProvider, + DynamicFormControlOptionDataProvider +} from '../model/misc/dynamic-form-control-data.model'; +import {Observable, of} from 'rxjs'; +import {Injectable} from '@angular/core'; +import {DynamicInputModel} from '../model/input/dynamic-input.model'; +import {DynamicFormGroupModel} from '../model/form-group/dynamic-form-group.model'; +import {DynamicFormOptionConfig} from '../model/dynamic-option-control.model'; + +@Injectable() +class TestProvider implements DynamicFormControlListDataProvider, DynamicFormControlOptionDataProvider { + fetchList(value: string): Observable { + return of(['test']); + } + + fetchOptions(value: string): Observable[]> { + return of([{ + label: 'Test', + value: 'test' + }]); + } +} + +@Injectable() +class InvalidTestProvider { + +} + +describe("DynamicFormDataService test suite", () => { + + let service: DynamicFormDataService, + group: FormGroup, + model: DynamicInputModel = new DynamicInputModel({ + id: "testInput2", + list: ['item-1', 'item-2', 'item-3'], + value: "item-1", + dataProvider: { + relation: { + id: 'testInput' + }, + service: TestProvider, + } + }), + select: DynamicSelectModel = new DynamicSelectModel({ + id: "testSelect", + options: [{value: "option-1"}, {value: "option-2"}, {value: "option-3"}], + value: "option-1", + dataProvider: { + relation: { + id: 'testInput' + }, + service: TestProvider, + } + }), + radio: DynamicRadioGroupModel = new DynamicRadioGroupModel({ + id: "testRadioGroup", + options: [{value: "option-1"}, {value: "option-2"}, {value: "option-3"}], + value: "option-1", + dataProvider: { + relation: { + id: 'testInput' + }, + service: TestProvider + } + }), + invalidListProvider: DynamicInputModel = new DynamicInputModel({ + id: "invalidListProvider", + list: ['item-1', 'item-2', 'item-3'], + value: "item-1", + dataProvider: { + relation: { + id: 'testInput' + }, + service: InvalidTestProvider, + } + }), + invalidOptionProvider: DynamicSelectModel = new DynamicSelectModel({ + id: "invalidOptionProvider", + options: [{value: "option-1"}, {value: "option-2"}, {value: "option-3"}], + value: "option-1", + dataProvider: { + relation: { + id: 'testInput' + }, + service: InvalidTestProvider, + } + }), + referenceInvalidControl: DynamicInputModel = new DynamicInputModel({ + id: "referenceInvalidControl", + list: ['item-1', 'item-2', 'item-3'], + value: "item-1", + dataProvider: { + relation: { + id: 'not-an-id' + }, + service: TestProvider, + } + }), + groupModel = new DynamicFormGroupModel({ + id: 'test', + group: [ + new DynamicRadioGroupModel({ + id: "testRootRadioGroup", + options: [{value: "option-1"}, {value: "option-2"}, {value: "option-3"}], + value: "option-1", + dataProvider: { + relation: { + id: 'testInput' + }, + service: TestProvider + } + }), + ] + }), + groupInputTest = new DynamicInputModel({ + id: "testInput", + dataProvider: { + relation: { + rootPath: 'test.testRootRadioGroup' + }, + service: TestProvider, + } + }) + ; + + beforeEach(() => { + + TestBed.configureTestingModule({ + imports: [ReactiveFormsModule], + providers: [DynamicFormDataService, TestProvider, InvalidTestProvider] + }); + }); + + beforeEach(inject([DynamicFormDataService, DynamicFormService], + (dataService: DynamicFormDataService, formService: DynamicFormService) => { + + service = dataService; + + group = formService.createFormGroup([ + new DynamicInputModel({id: "testInput"}), + model, + select, + radio, + invalidListProvider, + invalidOptionProvider, + groupModel + ]); + })); + + it("should get related form control correctly", () => { + const compareControl = group.get('testInput'); + const relatedFormControl = service.getRelatedFormControl(model, group); + + expect(relatedFormControl).toBe(compareControl); + }); + + it("should get data from provider on related input value change", fakeAsync(() => { + const triggerControl = group.get('testInput'); + + service.connectDynamicFormControls(model, group); + triggerControl.setValue('newVal'); + tick(401); + model.list$.subscribe((list) => expect(list[0]).toBe('test')); + })); + + it("should get data from provider on related select option value change", fakeAsync(() => { + const triggerControl = group.get('testInput'); + + service.connectDynamicFormControls(select, group); + triggerControl.setValue('newVal'); + tick(401); + select.options$.subscribe((options) => expect(options[0].value).toBe('test')); + })); + + it("should get data from provider on related radio option value change", fakeAsync(() => { + const triggerControl = group.get('testInput'); + + service.connectDynamicFormControls(radio, group); + triggerControl.setValue('newVal'); + tick(401); + radio.options$.subscribe((options) => expect(options[0].value).toBe('test')); + })); + + it("should not fail with invalid provider but receive warning with missing list data provider.", fakeAsync(() => { + const triggerControl = group.get('testInput'); + + service.connectDynamicFormControls(invalidListProvider, group); + triggerControl.setValue('newVal'); + tick(401); + invalidListProvider.list$.subscribe((list) => expect(list[0]).toBe('item-1')); + })); + + it("should not fail with invalid provider but receive warning with missing options data provider.", fakeAsync(() => { + const triggerControl = group.get('testInput'); + + service.connectDynamicFormControls(invalidOptionProvider, group); + triggerControl.setValue('newVal'); + tick(401); + invalidOptionProvider.options$.subscribe((options) => expect(options[0].value).toBe('option-1')); + })); + + it('should show warning with invalid relatedform control', () => { + const relatedFormControl = service.getRelatedFormControl(referenceInvalidControl, group); + expect(relatedFormControl).toBe(null); + }); + + it('should get related form control from rootPath', () => { + const compareControl = group.root.get('test.testRootRadioGroup'); + const relatedFormControl = service.getRelatedFormControl(groupInputTest, group); + + expect(relatedFormControl).toBe(compareControl); + }); +}); diff --git a/projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-data.service.ts b/projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-data.service.ts new file mode 100644 index 000000000..c2dd12f7d --- /dev/null +++ b/projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-data.service.ts @@ -0,0 +1,85 @@ +import { Injectable, Injector } from "@angular/core"; +import { AbstractControl, FormControl, FormGroup } from "@angular/forms"; +import { DynamicFormControlModel } from "../model/dynamic-form-control.model"; +import { debounceTime, startWith } from "rxjs/operators"; +import { Subscription } from "rxjs"; +import { DynamicInputModel } from '../model/input/dynamic-input.model'; +import { DynamicFormService } from './dynamic-form.service'; +import { DynamicOptionControlModel } from '../model/dynamic-option-control.model'; +import { + DynamicFormControlListDataProvider, + DynamicFormControlOptionDataProvider +} from '../model/misc/dynamic-form-control-data.model'; + +@Injectable({ + providedIn: "root" +}) +export class DynamicFormDataService { + + constructor(private injector: Injector) { + } + + getRelatedFormControl(model: DynamicFormControlModel, group: FormGroup): AbstractControl { + const relation = model.dataProvider.relation; + const control = relation.rootPath ? group.root.get(relation.rootPath) : group.get(relation.id); + + if (!(control instanceof FormControl)) { + console.warn(`No related form control with id ${relation.id} could be found`); + } + + return control; + } + + connectDynamicFormControls(model: DynamicFormControlModel, group: FormGroup): Subscription { + const relatedControl = this.getRelatedFormControl(model, group); + const valueChanges = relatedControl.valueChanges.pipe(startWith(relatedControl.value)); + + return valueChanges + .pipe(debounceTime(400)) + .subscribe((value) => { + if (model instanceof DynamicInputModel) { + this.populateList(value, model, this.injector); + } else if (model instanceof DynamicOptionControlModel) { + this.populateOptions(value, model, this.injector); + } + }); + } + + isListProvider(provider: DynamicFormControlListDataProvider): boolean { + return provider.fetchList !== undefined; + } + + isOptionProvider(provider: DynamicFormControlOptionDataProvider): boolean { + return provider.fetchOptions !== undefined; + } + + populateList(value, model, injector): void { + const provider = injector.get(model.dataProvider.service); + + if (!this.isListProvider(provider)) { + console.warn(`Data Service does not conform to DynamicFormControlListDataProvider interface for id ${model.id}`) + return; + } + + provider.fetchList(value) + .subscribe((val) => { + model.list = val; + injector.get(DynamicFormService).detectChanges(); + }); + } + + populateOptions(value, model, injector): void { + const provider = injector.get(model.dataProvider.service); + + if (!this.isOptionProvider(provider)) { + console.warn(`Data Service does not conform to DynamicFormControlOptionDataProvider interface for id ${model.id}`) + return; + } + + provider.fetchOptions(value) + .subscribe((val) => { + model.options = val; + injector.get(DynamicFormService).detectChanges(); + }); + } +} diff --git a/projects/ng-dynamic-forms/ui-basic/src/lib/dynamic-basic-form-control-container.component.ts b/projects/ng-dynamic-forms/ui-basic/src/lib/dynamic-basic-form-control-container.component.ts index 87aa10584..307a3b250 100644 --- a/projects/ng-dynamic-forms/ui-basic/src/lib/dynamic-basic-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/ui-basic/src/lib/dynamic-basic-form-control-container.component.ts @@ -32,7 +32,8 @@ import { DynamicFormLayoutService, DynamicFormRelationService, DynamicFormValidationService, - DynamicTemplateDirective + DynamicTemplateDirective, + DynamicFormDataService, } from "@ng-dynamic-forms/core"; import { DynamicBasicCheckboxComponent } from "./checkbox/dynamic-basic-checkbox.component"; import { DynamicBasicInputComponent } from "./input/dynamic-basic-input.component"; @@ -71,9 +72,10 @@ export class DynamicBasicFormControlContainerComponent extends DynamicFormContro protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { - super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService); + super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService, dataService); } get componentType(): Type | null { diff --git a/projects/ng-dynamic-forms/ui-bootstrap/src/lib/dynamic-bootstrap-form-control-container.component.ts b/projects/ng-dynamic-forms/ui-bootstrap/src/lib/dynamic-bootstrap-form-control-container.component.ts index 78009ee22..04d61fd23 100644 --- a/projects/ng-dynamic-forms/ui-bootstrap/src/lib/dynamic-bootstrap-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/ui-bootstrap/src/lib/dynamic-bootstrap-form-control-container.component.ts @@ -35,7 +35,8 @@ import { DynamicFormLayoutService, DynamicFormRelationService, DynamicFormValidationService, - DynamicTemplateDirective + DynamicTemplateDirective, + DynamicFormDataService, } from "@ng-dynamic-forms/core"; import { DynamicBootstrapCheckboxComponent } from "./checkbox/dynamic-bootstrap-checkbox.component"; import { DynamicBootstrapDatePickerComponent } from "./datepicker/dynamic-bootstrap-datepicker.component"; @@ -83,9 +84,10 @@ export class DynamicBootstrapFormControlContainerComponent extends DynamicFormCo protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { - super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService); + super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService, dataService); } } diff --git a/projects/ng-dynamic-forms/ui-foundation/src/lib/dynamic-foundation-form-control-container.component.ts b/projects/ng-dynamic-forms/ui-foundation/src/lib/dynamic-foundation-form-control-container.component.ts index 28de6f34e..f6fe70dee 100644 --- a/projects/ng-dynamic-forms/ui-foundation/src/lib/dynamic-foundation-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/ui-foundation/src/lib/dynamic-foundation-form-control-container.component.ts @@ -34,7 +34,8 @@ import { DynamicFormLayoutService, DynamicFormRelationService, DynamicFormValidationService, - DynamicTemplateDirective + DynamicTemplateDirective, + DynamicFormDataService, } from "@ng-dynamic-forms/core"; import { DynamicFoundationTextAreaComponent } from "./textarea/dynamic-foundation-textarea.component"; import { DynamicFoundationSwitchComponent } from "./switch/dynamic-foundation-switch.component"; @@ -74,9 +75,10 @@ export class DynamicFoundationFormControlContainerComponent extends DynamicFormC protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { - super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService); + super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService, dataService); } get componentType(): Type | null { diff --git a/projects/ng-dynamic-forms/ui-ionic/src/lib/dynamic-ionic-form-control-container.component.ts b/projects/ng-dynamic-forms/ui-ionic/src/lib/dynamic-ionic-form-control-container.component.ts index c58edb629..87f820b37 100644 --- a/projects/ng-dynamic-forms/ui-ionic/src/lib/dynamic-ionic-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/ui-ionic/src/lib/dynamic-ionic-form-control-container.component.ts @@ -37,7 +37,8 @@ import { DynamicFormLayoutService, DynamicFormRelationService, DynamicFormValidationService, - DynamicTemplateDirective + DynamicTemplateDirective, + DynamicFormDataService, } from "@ng-dynamic-forms/core"; import { DynamicIonicCheckboxComponent } from "./checkbox/dynamic-ionic-checkbox.component"; import { DynamicIonicDateTimeComponent } from "./datetime/dynamic-ionic-datetime.component"; @@ -80,9 +81,10 @@ export class DynamicIonicFormControlContainerComponent extends DynamicFormContro protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { - super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService); + super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService, dataService); } get componentType(): Type | null { diff --git a/projects/ng-dynamic-forms/ui-kendo/src/lib/dynamic-kendo-form-control-container.component.ts b/projects/ng-dynamic-forms/ui-kendo/src/lib/dynamic-kendo-form-control-container.component.ts index e5cb842de..8cc4639b1 100644 --- a/projects/ng-dynamic-forms/ui-kendo/src/lib/dynamic-kendo-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/ui-kendo/src/lib/dynamic-kendo-form-control-container.component.ts @@ -45,7 +45,8 @@ import { DynamicInputModel, DynamicSelectModel, DynamicTemplateDirective, - isString + isString, + DynamicFormDataService, } from "@ng-dynamic-forms/core"; import { DynamicKendoAutoCompleteComponent } from "./autocomplete/dynamic-kendo-autocomplete.component"; import { DynamicKendoCheckboxComponent } from "./checkbox/dynamic-kendo-checkbox.component"; @@ -97,9 +98,10 @@ export class DynamicKendoFormControlContainerComponent extends DynamicFormContro protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { - super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService); + super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService, dataService); } get componentType(): Type | null { diff --git a/projects/ng-dynamic-forms/ui-material/src/lib/dynamic-material-form-control-container.component.ts b/projects/ng-dynamic-forms/ui-material/src/lib/dynamic-material-form-control-container.component.ts index 1835ed840..6d482041b 100644 --- a/projects/ng-dynamic-forms/ui-material/src/lib/dynamic-material-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/ui-material/src/lib/dynamic-material-form-control-container.component.ts @@ -38,7 +38,8 @@ import { DynamicFormValidationService, DynamicInputModel, DynamicTemplateDirective, - DynamicFormValueControlModel + DynamicFormValueControlModel, + DynamicFormDataService, } from "@ng-dynamic-forms/core"; import { DynamicMaterialDatePickerComponent } from "./datepicker/dynamic-material-datepicker.component"; import { DynamicMaterialInputComponent } from "./input/dynamic-material-input.component"; @@ -82,9 +83,10 @@ export class DynamicMaterialFormControlContainerComponent extends DynamicFormCon protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { - super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService); + super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService, dataService); } get componentType(): Type | null { diff --git a/projects/ng-dynamic-forms/ui-ng-bootstrap/src/lib/dynamic-ng-bootstrap-form-control-container.component.ts b/projects/ng-dynamic-forms/ui-ng-bootstrap/src/lib/dynamic-ng-bootstrap-form-control-container.component.ts index dfcdd498f..5e715574a 100644 --- a/projects/ng-dynamic-forms/ui-ng-bootstrap/src/lib/dynamic-ng-bootstrap-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/ui-ng-bootstrap/src/lib/dynamic-ng-bootstrap-form-control-container.component.ts @@ -37,7 +37,8 @@ import { DynamicFormLayoutService, DynamicFormRelationService, DynamicFormValidationService, - DynamicTemplateDirective + DynamicTemplateDirective, + DynamicFormDataService, } from "@ng-dynamic-forms/core"; import { DynamicNGBootstrapCheckboxComponent } from "./checkbox/dynamic-ng-bootstrap-checkbox.component"; import { DynamicNGBootstrapCheckboxGroupComponent } from "./checkbox-group/dynamic-ng-bootstrap-checkbox-group.component"; @@ -84,9 +85,10 @@ export class DynamicNGBootstrapFormControlContainerComponent extends DynamicForm protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { - super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService); + super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService, dataService); } get componentType(): Type | null { diff --git a/projects/ng-dynamic-forms/ui-ngx-bootstrap/src/lib/dynamic-ngx-bootstrap-form-control-container.component.ts b/projects/ng-dynamic-forms/ui-ngx-bootstrap/src/lib/dynamic-ngx-bootstrap-form-control-container.component.ts index f66ebed71..d6f02550e 100644 --- a/projects/ng-dynamic-forms/ui-ngx-bootstrap/src/lib/dynamic-ngx-bootstrap-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/ui-ngx-bootstrap/src/lib/dynamic-ngx-bootstrap-form-control-container.component.ts @@ -32,6 +32,7 @@ import { DynamicFormControlContainerComponent, DynamicFormControlEvent, DynamicFormControlModel, + DynamicFormDataService, DynamicFormLayout, DynamicFormLayoutService, DynamicFormRelationService, @@ -85,9 +86,10 @@ export class DynamicNGxBootstrapFormControlContainerComponent extends DynamicFor protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { - super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService); + super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService, dataService); } } diff --git a/projects/ng-dynamic-forms/ui-primeng/src/lib/dynamic-primeng-form-control-container.component.ts b/projects/ng-dynamic-forms/ui-primeng/src/lib/dynamic-primeng-form-control-container.component.ts index 1fd377234..116bbb232 100644 --- a/projects/ng-dynamic-forms/ui-primeng/src/lib/dynamic-primeng-form-control-container.component.ts +++ b/projects/ng-dynamic-forms/ui-primeng/src/lib/dynamic-primeng-form-control-container.component.ts @@ -37,6 +37,7 @@ import { DynamicFormControlContainerComponent, DynamicFormControlEvent, DynamicFormControlModel, + DynamicFormDataService, DynamicFormLayout, DynamicFormLayoutService, DynamicFormRelationService, @@ -94,9 +95,10 @@ export class DynamicPrimeNGFormControlContainerComponent extends DynamicFormCont protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected componentService: DynamicFormComponentService, - protected relationService: DynamicFormRelationService) { + protected relationService: DynamicFormRelationService, + protected dataService: DynamicFormDataService) { - super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService); + super(changeDetectorRef, componentFactoryResolver, layoutService, validationService, componentService, relationService, dataService); } get componentType(): Type | null {