Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): support custom model json map fn injectionToken #1009

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
NG_VALIDATORS,
NG_ASYNC_VALIDATORS
} from "@angular/forms";
import { DynamicFormService } from "./dynamic-form.service";
import { DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN, DynamicFormControlModelConfigMapFn, DynamicFormService } from './dynamic-form.service';
import { DynamicFormValidationService } from "./dynamic-form-validation.service";
import { DynamicFormModel } from "../model/dynamic-form.model";
import { DynamicCheckboxModel } from "../model/checkbox/dynamic-checkbox.model";
Expand Down Expand Up @@ -35,6 +35,21 @@ describe("DynamicFormService test suite", () => {
let testModel: DynamicFormModel,
service: DynamicFormService;

const DYNAMIC_FORM_CONTROL_TYPE_CUSTOM = "CUSTOM";

class DynamicCustomModel extends DynamicInputModel {
readonly type = DYNAMIC_FORM_CONTROL_TYPE_CUSTOM;
}

const dynamicFormControlModelConfigMapFn: DynamicFormControlModelConfigMapFn = (model, layout, formService) => {
switch (model.type) {
case DYNAMIC_FORM_CONTROL_TYPE_CUSTOM:
return new DynamicCustomModel(model, layout);
default:
return null;
}
}

function testValidator() {
return {testValidator: {valid: true}};
}
Expand All @@ -50,6 +65,7 @@ describe("DynamicFormService test suite", () => {
providers: [
DynamicFormService,
DynamicFormValidationService,
{provide: DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN, useValue: dynamicFormControlModelConfigMapFn},
{provide: NG_VALIDATORS, useValue: testValidator, multi: true},
{provide: NG_ASYNC_VALIDATORS, useValue: testAsyncValidator, multi: true}
]
Expand Down Expand Up @@ -220,6 +236,17 @@ describe("DynamicFormService test suite", () => {
});


it("should parse dynamic custom control JSON", () => {
const model = { id: 'custom', type: DYNAMIC_FORM_CONTROL_TYPE_CUSTOM },
unknownModel = { id: 'unknownType', type: "UNKNOWN" },
json = JSON.stringify([model]),
formModel = service.fromJSON(json);

expect(formModel[0] instanceof DynamicCustomModel).toBe(true);
expect(service.getCustomComponentModel(model, null)).toBeDefined();
expect(service.getCustomComponentModel(unknownModel, null)).toBeNull();
});

it("should throw when unknown DynamicFormControlModel id is specified in JSON", () => {

expect(() => service.fromJSON([{id: "test"}]))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable } from "@angular/core";
import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
import { AbstractControl, FormArray, FormControl, FormGroup } from "@angular/forms";
import { AbstractControlOptions } from "@angular/forms";
import { DynamicFormControlModel, FormHooks } from "../model/dynamic-form-control.model";
Expand Down Expand Up @@ -46,14 +46,24 @@ import { DynamicFormModel, DynamicUnionFormModel } from "../model/dynamic-form.m
import { DynamicPathable } from "../model/misc/dynamic-form-control-path.model";
import { DynamicValidatorsConfig } from "../model/misc/dynamic-form-control-validation.model";
import { maskFromString, parseReviver } from "../utils/json.utils";
import { isString } from "../utils/core.utils";
import { isFunction, isString } from '../utils/core.utils';

export type DynamicFormControlModelConfigMapFn = (model: any, layout: any, formService: DynamicFormService) => DynamicFormControlModel | null;
export const DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN = new InjectionToken<DynamicFormControlModelConfigMapFn>(
'DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN'
);

@Injectable({
providedIn: "root"
})
export class DynamicFormService {

constructor(private validationService: DynamicFormValidationService) {}
constructor(private validationService: DynamicFormValidationService,
@Inject(DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN) @Optional()
private readonly DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN: any,
) {
this.DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN = DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN as DynamicFormControlModelConfigMapFn;
}


private createAbstractControlOptions(validatorsConfig: DynamicValidatorsConfig | null = null,
Expand Down Expand Up @@ -323,6 +333,12 @@ export class DynamicFormService {
formModelJSON.forEach((model: any) => {

let layout = model.layout || null;
let customModel = this.getCustomComponentModel(model, layout);

if (customModel) {
formModel.push(customModel);
return;
}

switch (model.type) {

Expand Down Expand Up @@ -421,4 +437,10 @@ export class DynamicFormService {

return formModel;
}

getCustomComponentModel(model: object, layout: any): DynamicFormControlModel | null {
return isFunction(this.DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN)
? this.DYNAMIC_FORM_CONTROL_MODEL_CONFIG_MAP_FN(model, layout, this)
: null;
}
}