UNPKG

@ng-dynamic-forms/core

Version:

A rapid form development library for Angular

1 lines 206 kB
{"version":3,"file":"core.mjs","sources":["../../../../projects/ng-dynamic-forms/core/src/lib/utils/core.utils.ts","../../../../projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-control.component.ts","../../../../projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-array.component.ts","../../../../projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-group.component.ts","../../../../projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-component.service.ts","../../../../projects/ng-dynamic-forms/core/src/lib/component/dynamic-form.component.ts","../../../../projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-control-event.ts","../../../../projects/ng-dynamic-forms/core/src/lib/decorator/serializable.decorator.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/dynamic-form-control.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/dynamic-form-value-control.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/form-array/dynamic-form-array.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/dynamic-check-control.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/checkbox/dynamic-checkbox.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/dynamic-input-control.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/input/dynamic-input.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/directive/dynamic-template.directive.ts","../../../../projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-layout.service.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/misc/dynamic-form-control-validation.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-validators.ts","../../../../projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-validation-matchers.ts","../../../../projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-validation.service.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/form-group/dynamic-form-group.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/checkbox/dynamic-checkbox-group.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/colorpicker/dynamic-colorpicker.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/dynamic-date-control.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/datepicker/dynamic-datepicker.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/editor/dynamic-editor.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/dynamic-file-control.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/file-upload/dynamic-file-upload.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/dynamic-option-control.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/radio/dynamic-radio-group.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/rating/dynamic-rating.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/select/dynamic-select.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/slider/dynamic-slider.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/switch/dynamic-switch.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/textarea/dynamic-textarea.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/model/timepicker/dynamic-timepicker.model.ts","../../../../projects/ng-dynamic-forms/core/src/lib/utils/json.utils.ts","../../../../projects/ng-dynamic-forms/core/src/lib/service/dynamic-form.service.ts","../../../../projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-relation-matchers.ts","../../../../projects/ng-dynamic-forms/core/src/lib/service/dynamic-form-relation.service.ts","../../../../projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-control-container.component.ts","../../../../projects/ng-dynamic-forms/core/src/lib/component/dynamic-form-control-with-template.component.ts","../../../../projects/ng-dynamic-forms/core/src/lib/directive/dynamic-list.directive.ts","../../../../projects/ng-dynamic-forms/core/src/lib/utils/autofill.utils.ts","../../../../projects/ng-dynamic-forms/core/src/lib/core.module.ts","../../../../projects/ng-dynamic-forms/core/src/core.ts"],"sourcesContent":["export function isBoolean(value: any): value is boolean {\n return typeof value === \"boolean\";\n}\n\n// tslint:disable-next-line:ban-types\nexport function isFunction(value: any): value is Function {\n return typeof value === \"function\";\n}\n\nexport function isNumber(value: any): value is number {\n return typeof value === \"number\";\n}\n\nexport function isObject(value: any): value is object {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function isString(value: any): value is string {\n return typeof value === \"string\";\n}\n","import { EventEmitter } from \"@angular/core\";\nimport { AbstractControl, UntypedFormGroup } from \"@angular/forms\";\nimport { DynamicFormControl } from \"./dynamic-form-control-interface\";\nimport { DynamicFormControlCustomEvent } from \"./dynamic-form-control-event\";\nimport { DynamicFormControlModel } from \"../model/dynamic-form-control.model\";\nimport {\n DynamicFormControlLayout,\n DynamicFormControlLayoutContext,\n DynamicFormControlLayoutPlace\n} from \"../model/misc/dynamic-form-control-layout.model\";\nimport { DynamicFormValidationService } from \"../service/dynamic-form-validation.service\";\nimport {\n DynamicFormLayout,\n DynamicFormLayoutService,\n DynamicFormControlTemplates\n} from \"../service/dynamic-form-layout.service\";\nimport { isString } from \"../utils/core.utils\";\n\nexport abstract class DynamicFormControlComponent implements DynamicFormControl {\n formLayout?: DynamicFormLayout;\n group!: UntypedFormGroup;\n layout?: DynamicFormControlLayout;\n model!: DynamicFormControlModel;\n templates?: DynamicFormControlTemplates;\n\n blur!: EventEmitter<any>;\n change!: EventEmitter<any>;\n customEvent?: EventEmitter<DynamicFormControlCustomEvent>;\n focus!: EventEmitter<any>;\n\n private _hasFocus = false;\n\n protected constructor(protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService) {\n }\n\n get control(): AbstractControl | never {\n const control = this.group.get(this.model.id);\n\n if (control === null) {\n throw new Error(`form group does not contain an abstract control with id ${this.model.id}`);\n }\n\n return control;\n }\n\n get id(): string {\n return this.layoutService.getElementId(this.model);\n }\n\n get hasFocus(): boolean {\n return this._hasFocus;\n }\n\n get isInvalid(): boolean {\n return this.control.invalid;\n }\n\n get isValid(): boolean {\n return this.control.valid;\n }\n\n get errorMessages(): string[] {\n return this.validationService.createErrorMessages(this.control, this.model);\n }\n\n get showErrorMessages(): boolean {\n return this.validationService.showErrorMessages(this.control, this.model, this.hasFocus);\n }\n\n getClass(context: DynamicFormControlLayoutContext, place: DynamicFormControlLayoutPlace,\n model: DynamicFormControlModel = this.model): string {\n const controlLayout = model === this.model ? this.layout :\n this.layoutService.findByModel(model, this.formLayout) ?? model.layout as DynamicFormControlLayout;\n\n return this.layoutService.getClass(controlLayout, context, place);\n }\n\n onBlur($event: any) {\n if ($event instanceof Event) {\n $event.stopPropagation();\n }\n\n this._hasFocus = false;\n this.blur.emit($event);\n }\n\n onChange($event: any) {\n if ($event instanceof Event) {\n $event.stopPropagation();\n }\n\n this.change.emit($event);\n }\n\n onCustomEvent($event: any, type: string | null = null, bypass: boolean = false) {\n if (bypass) {\n this.customEvent?.emit($event);\n\n } else if (isString(type)) {\n this.customEvent?.emit({customEvent: $event, customEventType: type});\n }\n }\n\n onFocus($event: any) {\n if ($event instanceof Event) {\n $event.stopPropagation();\n }\n\n this._hasFocus = true;\n this.focus.emit($event);\n }\n}\n","import { QueryList } from \"@angular/core\";\nimport { UntypedFormArray } from \"@angular/forms\";\nimport { DynamicFormControlComponent } from \"./dynamic-form-control.component\";\nimport { DynamicTemplateDirective } from \"../directive/dynamic-template.directive\";\nimport { DynamicFormArrayModel } from \"../model/form-array/dynamic-form-array.model\";\nimport { DynamicFormControlContainerComponent } from \"./dynamic-form-control-container.component\";\n\nexport abstract class DynamicFormArrayComponent extends DynamicFormControlComponent {\n components!: QueryList<DynamicFormControlContainerComponent>;\n model!: DynamicFormArrayModel;\n templates?: QueryList<DynamicTemplateDirective>;\n\n get array(): UntypedFormArray {\n return this.control as UntypedFormArray;\n }\n\n get startTemplate(): DynamicTemplateDirective | undefined {\n return this.layoutService.getStartTemplate(this.model, this.templates);\n }\n\n get endTemplate(): DynamicTemplateDirective | undefined {\n return this.layoutService.getEndTemplate(this.model, this.templates);\n }\n\n markForCheck() {\n if (this.components instanceof QueryList) {\n this.components.forEach(component => component.markForCheck());\n }\n }\n}\n","import { DynamicFormControlComponent } from \"./dynamic-form-control.component\";\nimport { DynamicFormGroupModel } from \"../model/form-group/dynamic-form-group.model\";\nimport { QueryList } from \"@angular/core\";\nimport { DynamicFormControlContainerComponent } from \"./dynamic-form-control-container.component\";\n\nexport abstract class DynamicFormGroupComponent extends DynamicFormControlComponent {\n components!: QueryList<DynamicFormControlContainerComponent>;\n model!: DynamicFormGroupModel;\n\n markForCheck() {\n if (this.components instanceof QueryList) {\n this.components.forEach(component => component.markForCheck());\n }\n }\n}\n","import { ComponentRef, Inject, Injectable, InjectionToken, Optional, Type } from \"@angular/core\";\nimport { DynamicFormControl } from \"../component/dynamic-form-control-interface\";\nimport { DynamicFormComponent } from \"../component/dynamic-form.component\";\nimport { DynamicFormControlModel } from \"../model/dynamic-form-control.model\";\nimport { isFunction, isNumber } from \"../utils/core.utils\";\n\nexport type DynamicFormControlRef = ComponentRef<DynamicFormControl>;\nexport type DynamicFormControlMapFn = (model: DynamicFormControlModel) => Type<DynamicFormControl> | null;\n\nexport const DYNAMIC_FORM_CONTROL_MAP_FN = new InjectionToken<DynamicFormControlMapFn>(\"DYNAMIC_FORM_CONTROL_MAP_FN\");\n\n@Injectable({\n providedIn: \"root\"\n})\nexport class DynamicFormComponentService {\n private forms: DynamicFormComponent[] = [];\n private formControls: { [key: string]: DynamicFormControlRef | DynamicFormControlRef[] } = {};\n\n constructor(@Inject(DYNAMIC_FORM_CONTROL_MAP_FN) @Optional() private readonly DYNAMIC_FORM_CONTROL_MAP_FN: any) {\n this.DYNAMIC_FORM_CONTROL_MAP_FN = DYNAMIC_FORM_CONTROL_MAP_FN as DynamicFormControlMapFn;\n }\n\n getForms(): IterableIterator<DynamicFormComponent> {\n return this.forms.values();\n }\n\n registerForm(component: DynamicFormComponent): void {\n this.forms.push(component);\n }\n\n unregisterForm(component: DynamicFormComponent): void {\n const indexOf = this.forms.indexOf(component);\n\n if (indexOf !== -1) {\n this.forms.splice(indexOf, 1);\n }\n }\n\n getFormControlRef(modelId: string, index?: number): DynamicFormControlRef | undefined {\n const ref: DynamicFormControlRef | DynamicFormControlRef[] = this.formControls[modelId];\n\n if (isNumber(index)) {\n return Array.isArray(ref) ? ref[index] : undefined;\n\n } else {\n return ref as DynamicFormControlRef;\n }\n }\n\n registerFormControl(model: DynamicFormControlModel, ref: DynamicFormControlRef, index?: number): void {\n if (isNumber(index)) { // threat model as array child\n const arrayRef: DynamicFormControlRef[] = this.formControls[model.id] as DynamicFormControlRef[] || [];\n\n if (Array.isArray(arrayRef)) {\n arrayRef.splice(index, 0, ref);\n this.formControls[model.id] = arrayRef;\n\n } else {\n console.warn(`registerFormControlRef is called with index for a non-array form control: ${model.id}`);\n }\n\n } else {\n this.formControls[model.id] = ref;\n }\n }\n\n unregisterFormControl(modelId: string, index?: number): void {\n const componentRef = this.formControls[modelId];\n\n if (isNumber(index)) {\n if (Array.isArray(componentRef) && componentRef[index] !== undefined) {\n componentRef.splice(index, 1);\n }\n\n } else if (componentRef !== undefined) {\n delete this.formControls[modelId];\n }\n }\n\n getCustomComponentType(model: DynamicFormControlModel): Type<DynamicFormControl> | null {\n return isFunction(this.DYNAMIC_FORM_CONTROL_MAP_FN) ? this.DYNAMIC_FORM_CONTROL_MAP_FN(model) : null;\n }\n}\n","import { ChangeDetectorRef, Directive, EventEmitter, OnDestroy, OnInit, QueryList } from \"@angular/core\";\nimport { UntypedFormGroup } from \"@angular/forms\";\nimport { DynamicFormControlContainerComponent } from \"./dynamic-form-control-container.component\";\nimport { DynamicFormControlEvent } from \"./dynamic-form-control-event\";\nimport { DynamicFormControlModel } from \"../model/dynamic-form-control.model\";\nimport { DynamicFormModel } from \"../model/dynamic-form.model\";\nimport { DynamicTemplateDirective } from \"../directive/dynamic-template.directive\";\nimport { DynamicFormLayout } from \"../service/dynamic-form-layout.service\";\nimport { DynamicFormComponentService } from \"../service/dynamic-form-component.service\";\n\n@Directive()\n// tslint:disable-next-line:directive-class-suffix\nexport abstract class DynamicFormComponent implements OnInit, OnDestroy {\n group!: UntypedFormGroup;\n model!: DynamicFormModel;\n layout?: DynamicFormLayout;\n\n components!: QueryList<DynamicFormControlContainerComponent>;\n templates!: QueryList<DynamicTemplateDirective>;\n\n blur?: EventEmitter<DynamicFormControlEvent>;\n change?: EventEmitter<DynamicFormControlEvent>;\n focus?: EventEmitter<DynamicFormControlEvent>;\n\n protected constructor(protected changeDetectorRef: ChangeDetectorRef, protected componentService: DynamicFormComponentService) {\n }\n\n ngOnInit(): void {\n this.componentService.registerForm(this);\n }\n\n ngOnDestroy(): void {\n this.componentService.unregisterForm(this);\n }\n\n trackByFn(_index: number, model: DynamicFormControlModel): string {\n return model.id;\n }\n\n markForCheck(): void {\n this.changeDetectorRef.markForCheck();\n\n if (this.components instanceof QueryList) {\n this.components.forEach(component => component.markForCheck());\n }\n }\n\n detectChanges(): void {\n this.changeDetectorRef.detectChanges();\n }\n\n onBlur($event: DynamicFormControlEvent) {\n this.blur?.emit($event);\n }\n\n onChange($event: DynamicFormControlEvent) {\n this.change?.emit($event);\n }\n\n onFocus($event: DynamicFormControlEvent) {\n this.focus?.emit($event);\n }\n\n onCustomEvent($event: DynamicFormControlEvent, customEventEmitter: EventEmitter<DynamicFormControlEvent>) {\n customEventEmitter.emit($event);\n }\n}\n","import { UntypedFormControl, UntypedFormGroup } from \"@angular/forms\";\nimport { DynamicFormControlModel } from \"../model/dynamic-form-control.model\";\nimport { DynamicFormArrayGroupModel } from \"../model/form-array/dynamic-form-array.model\";\nimport { isObject } from \"../utils/core.utils\";\n\nexport enum DynamicFormControlEventType {\n Blur = \"blur\",\n Change = \"change\",\n Focus = \"focus\"\n}\n\nexport interface DynamicFormControlEvent {\n $event: Event | FocusEvent | DynamicFormControlEvent | any;\n context: DynamicFormArrayGroupModel | null;\n control: UntypedFormControl;\n group: UntypedFormGroup;\n model: DynamicFormControlModel;\n type: string;\n}\n\nexport interface DynamicFormControlCustomEvent {\n customEvent: any;\n customEventType: string;\n}\n\nexport function isDynamicFormControlEvent($event: any): $event is DynamicFormControlEvent {\n return isObject($event) && $event.hasOwnProperty(\"$event\");\n}\n","import \"reflect-metadata\";\n\ndeclare let Reflect: any;\n\nexport const METADATA_KEY_SERIALIZABLE = \"SERIALIZABLE\";\n\nexport interface SerializableProperty {\n key: string;\n name: string;\n}\n\nexport function serializable(name?: string): (target: any, key: string) => void {\n return (target, key) => {\n Reflect.defineMetadata(METADATA_KEY_SERIALIZABLE, {key, name: name || key}, target, key);\n };\n}\n\nexport function getSerializables(target: any): SerializableProperty[] {\n const serializables = [];\n\n // tslint:disable-next-line:forin\n for (const key in target) {\n const metadata = Reflect.getMetadata(METADATA_KEY_SERIALIZABLE, target, key);\n\n if (metadata) {\n serializables.push(metadata);\n }\n }\n\n return serializables;\n}\n\nexport function serialize(target: any, prototype?: any): object {\n return getSerializables(prototype || target).reduce((prev: any, prop: SerializableProperty) => {\n\n prev[prop.name] = target[prop.key];\n\n return prev;\n\n }, {});\n}\n","import { BehaviorSubject, Observable } from \"rxjs\";\nimport { DynamicFormControlLayout } from \"./misc/dynamic-form-control-layout.model\";\nimport { DynamicPathable } from \"./misc/dynamic-form-control-path.model\";\nimport { DynamicFormControlRelation } from \"./misc/dynamic-form-control-relation.model\";\nimport { DynamicFormHook, DynamicValidatorsConfig } from \"./misc/dynamic-form-control-validation.model\";\nimport { serializable, serialize } from \"../decorator/serializable.decorator\";\nimport { isBoolean, isObject, isString } from \"../utils/core.utils\";\n\nexport interface DynamicFormControlModelConfig {\n asyncValidators?: DynamicValidatorsConfig;\n disabled?: boolean;\n errorMessages?: DynamicValidatorsConfig;\n hidden?: boolean;\n id: string;\n label?: string;\n labelTooltip?: string;\n controlTooltip?: string;\n name?: string;\n relations?: DynamicFormControlRelation[];\n updateOn?: DynamicFormHook;\n validators?: DynamicValidatorsConfig;\n}\n\nexport abstract class DynamicFormControlModel implements DynamicPathable {\n @serializable() asyncValidators: DynamicValidatorsConfig | null;\n @serializable(\"disabled\") _disabled: boolean;\n @serializable() errorMessages: DynamicValidatorsConfig | null;\n @serializable() hidden: boolean;\n @serializable() id: string;\n @serializable() label: string | null;\n @serializable() labelTooltip: string | null;\n @serializable() controlTooltip: string | null;\n @serializable() layout: DynamicFormControlLayout | null;\n @serializable() name: string;\n parent: DynamicPathable | null = null;\n @serializable() relations: DynamicFormControlRelation[];\n @serializable() updateOn: DynamicFormHook | null;\n @serializable() validators: DynamicValidatorsConfig | null;\n\n private readonly disabled$: BehaviorSubject<boolean>;\n\n readonly disabledChanges: Observable<boolean>;\n\n abstract readonly type: string;\n\n protected constructor(config: DynamicFormControlModelConfig, layout: DynamicFormControlLayout | null = null) {\n this.asyncValidators = config.asyncValidators ?? null;\n this.errorMessages = config.errorMessages ?? null;\n this.hidden = isBoolean(config.hidden) ? config.hidden : false;\n this.id = config.id;\n this.label = config.label ?? null;\n this.labelTooltip = config.labelTooltip ?? null;\n this.controlTooltip = config.controlTooltip ?? null;\n this.layout = layout;\n this.name = config.name ?? config.id;\n this.relations = Array.isArray(config.relations) ? config.relations : [];\n this.updateOn = isString(config.updateOn) ? config.updateOn : null;\n this.validators = config.validators ?? null;\n\n this._disabled = isBoolean(config.disabled) ? config.disabled : false;\n this.disabled$ = new BehaviorSubject(this._disabled);\n this.disabled$.subscribe(disabled => this._disabled = disabled);\n this.disabledChanges = this.disabled$.asObservable();\n }\n\n get disabled(): boolean {\n return this.disabled$.getValue();\n }\n\n set disabled(disabled: boolean) {\n this.disabled$.next(disabled);\n }\n\n get hasErrorMessages(): boolean {\n return isObject(this.errorMessages);\n }\n\n toJSON() {\n return serialize(this);\n }\n}\n","import { BehaviorSubject, Observable } from \"rxjs\";\nimport { DynamicFormControlModel, DynamicFormControlModelConfig } from \"./dynamic-form-control.model\";\nimport { DynamicFormControlLayout } from \"./misc/dynamic-form-control-layout.model\";\nimport { serializable } from \"../decorator/serializable.decorator\";\nimport { isBoolean, isObject } from \"../utils/core.utils\";\n\nexport interface DynamicFormValueControlModelConfig<T> extends DynamicFormControlModelConfig {\n additional?: { [key: string]: any };\n hint?: string;\n required?: boolean;\n tabIndex?: number;\n value?: T;\n}\n\nexport abstract class DynamicFormValueControlModel<T> extends DynamicFormControlModel {\n @serializable() additional: { [key: string]: any } | null;\n @serializable() hint: string | null;\n @serializable() required: boolean;\n @serializable() tabIndex: number | null;\n @serializable(\"value\") private _value: T | null;\n\n private readonly value$: BehaviorSubject<T | null>;\n\n readonly valueChanges: Observable<T | null>;\n\n protected constructor(config: DynamicFormValueControlModelConfig<T>, layout?: DynamicFormControlLayout) {\n super(config, layout);\n\n this.additional = isObject(config.additional) ? config.additional : null;\n this.hint = config.hint ?? null;\n this.required = isBoolean(config.required) ? config.required : false;\n this.tabIndex = config.tabIndex ?? null;\n\n this._value = config.value ?? null;\n this.value$ = new BehaviorSubject(this._value);\n this.value$.subscribe(value => this._value = value);\n this.valueChanges = this.value$.asObservable();\n }\n\n get value(): T | null {\n return this.value$.getValue();\n }\n\n set value(value: T | null) {\n this.value$.next(value);\n }\n\n getAdditional(key: string, defaultValue?: any | null): any {\n return this.additional !== null && this.additional.hasOwnProperty(key) ? this.additional[key] : defaultValue;\n }\n}\n","import { DynamicFormControlModel, DynamicFormControlModelConfig } from \"../dynamic-form-control.model\";\nimport { DynamicFormModel } from \"../dynamic-form.model\";\nimport { DynamicFormControlLayout } from \"../misc/dynamic-form-control-layout.model\";\nimport { DynamicPathable } from \"../misc/dynamic-form-control-path.model\";\nimport { DynamicValidatorsConfig } from \"../misc/dynamic-form-control-validation.model\";\nimport { serializable, serialize } from \"../../decorator/serializable.decorator\";\nimport { isFunction, isNumber } from \"../../utils/core.utils\";\n\nexport class DynamicFormArrayGroupModel implements DynamicPathable {\n $implicit: DynamicFormArrayGroupModel;\n context: DynamicFormArrayModel;\n @serializable() group: DynamicFormModel;\n @serializable() index: number;\n\n constructor(context: DynamicFormArrayModel, group: DynamicFormModel = [], index: number = -1) {\n this.$implicit = this;\n this.context = context;\n this.group = group;\n this.index = index;\n }\n\n get parent(): DynamicFormArrayModel {\n return this.context;\n }\n\n get(index: number): DynamicFormControlModel {\n return this.group[index];\n }\n\n toJSON() {\n return serialize(this);\n }\n}\n\nexport const DYNAMIC_FORM_CONTROL_TYPE_ARRAY = \"ARRAY\";\n\nexport interface DynamicFormArrayModelConfig extends DynamicFormControlModelConfig {\n groupAsyncValidators?: DynamicValidatorsConfig;\n groupFactory?: () => DynamicFormModel;\n groupValidators?: DynamicValidatorsConfig;\n groups?: DynamicFormArrayGroupModel[] | null;\n initialCount?: number;\n}\n\nexport class DynamicFormArrayModel extends DynamicFormControlModel {\n @serializable() groupAsyncValidators: DynamicValidatorsConfig | null;\n groupFactory: () => DynamicFormModel;\n @serializable() groupValidators: DynamicValidatorsConfig | null;\n @serializable() groups: DynamicFormArrayGroupModel[] = [];\n @serializable() initialCount: number;\n\n @serializable() readonly groupPrototype: DynamicFormModel; // only to recreate model from JSON\n @serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_ARRAY;\n\n constructor(config: DynamicFormArrayModelConfig, layout?: DynamicFormControlLayout) {\n super(config, layout);\n\n if (isFunction(config.groupFactory)) {\n this.groupFactory = config.groupFactory;\n } else {\n throw new Error(\"group factory function must be specified for DynamicFormArrayModel\");\n }\n\n this.groupAsyncValidators = config.groupAsyncValidators ?? null;\n this.groupPrototype = this.groupFactory();\n this.groupValidators = config.groupValidators ?? null;\n this.initialCount = isNumber(config.initialCount) ? config.initialCount : 1;\n\n if (Array.isArray(config.groups)) {\n config.groups.forEach((arrayGroup, index) => {\n this.groups.push(new DynamicFormArrayGroupModel(this, arrayGroup.group, arrayGroup.index ?? index));\n });\n\n } else {\n for (let index = 0; index < this.initialCount; index++) {\n this.addGroup();\n }\n }\n }\n\n private updateGroupIndex(): void {\n this.groups.forEach((group, index) => group.index = index);\n }\n\n get size(): number {\n return this.groups.length;\n }\n\n get(index: number): DynamicFormArrayGroupModel {\n return this.groups[index];\n }\n\n addGroup(): DynamicFormArrayGroupModel {\n return this.insertGroup(this.groups.length);\n }\n\n insertGroup(index: number): DynamicFormArrayGroupModel {\n const group = new DynamicFormArrayGroupModel(this, this.groupFactory());\n\n this.groups.splice(index, 0, group);\n this.updateGroupIndex();\n\n return group;\n }\n\n moveGroup(index: number, step: number): void {\n this.groups.splice(index + step, 0, ...this.groups.splice(index, 1));\n this.updateGroupIndex();\n }\n\n removeGroup(index: number): void {\n this.groups.splice(index, 1);\n this.updateGroupIndex();\n }\n\n clear(): void {\n this.groups.splice(0);\n this.updateGroupIndex();\n }\n}\n","import { DynamicFormValueControlModel, DynamicFormValueControlModelConfig } from \"./dynamic-form-value-control.model\";\nimport { DynamicFormControlLayout } from \"./misc/dynamic-form-control-layout.model\";\nimport { serializable } from \"../decorator/serializable.decorator\";\nimport { isBoolean } from \"../utils/core.utils\";\n\nexport interface DynamicCheckControlModelConfig extends DynamicFormValueControlModelConfig<boolean> {\n labelPosition?: string;\n}\n\nexport abstract class DynamicCheckControlModel extends DynamicFormValueControlModel<boolean> {\n @serializable() labelPosition: string | null;\n\n protected constructor(config: DynamicCheckControlModelConfig, layout?: DynamicFormControlLayout) {\n super(config, layout);\n\n this.labelPosition = config.labelPosition ?? null;\n this.checked = isBoolean(this.value) ? this.value : false;\n }\n\n get checked(): boolean {\n return this.value ?? false;\n }\n\n set checked(checked: boolean) {\n this.value = checked;\n }\n\n toggle(): void {\n this.checked = !this.checked;\n }\n}\n","import { DynamicCheckControlModel, DynamicCheckControlModelConfig } from \"../dynamic-check-control.model\";\nimport { DynamicFormControlLayout } from \"../misc/dynamic-form-control-layout.model\";\nimport { serializable } from \"../../decorator/serializable.decorator\";\nimport { isBoolean } from \"../../utils/core.utils\";\n\nexport const DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX = \"CHECKBOX\";\n\nexport interface DynamicCheckboxModelConfig extends DynamicCheckControlModelConfig {\n indeterminate?: boolean;\n}\n\nexport class DynamicCheckboxModel extends DynamicCheckControlModel {\n @serializable() indeterminate: boolean;\n\n @serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX;\n\n constructor(config: DynamicCheckboxModelConfig, layout?: DynamicFormControlLayout) {\n super(config, layout);\n\n this.indeterminate = isBoolean(config.indeterminate) ? config.indeterminate : false;\n }\n}\n","import { DynamicFormValueControlModel, DynamicFormValueControlModelConfig } from \"./dynamic-form-value-control.model\";\nimport { DynamicFormControlLayout } from \"./misc/dynamic-form-control-layout.model\";\nimport { serializable } from \"../decorator/serializable.decorator\";\nimport { isBoolean, isNumber } from \"../utils/core.utils\";\n\nexport interface DynamicInputControlModelConfig<T> extends DynamicFormValueControlModelConfig<T> {\n autoComplete?: string;\n autoFocus?: boolean;\n maxLength?: number;\n minLength?: number;\n placeholder?: string;\n prefix?: string;\n readOnly?: boolean;\n spellCheck?: boolean;\n suffix?: string;\n}\n\nexport abstract class DynamicInputControlModel<T> extends DynamicFormValueControlModel<T> {\n @serializable() autoComplete: string;\n @serializable() autoFocus: boolean;\n @serializable() maxLength: number | null;\n @serializable() minLength: number | null;\n @serializable() placeholder: string;\n @serializable() prefix: string | null;\n @serializable() readOnly: boolean;\n @serializable() spellCheck: boolean;\n @serializable() suffix: string | null;\n\n protected constructor(config: DynamicInputControlModelConfig<T>, layout?: DynamicFormControlLayout) {\n super(config, layout);\n\n this.autoComplete = config.autoComplete ?? \"on\";\n this.autoFocus = isBoolean(config.autoFocus) ? config.autoFocus : false;\n this.maxLength = isNumber(config.maxLength) ? config.maxLength : null;\n this.minLength = isNumber(config.minLength) ? config.minLength : null;\n this.placeholder = config.placeholder ?? \"\";\n this.prefix = config.prefix ?? null;\n this.readOnly = isBoolean(config.readOnly) ? config.readOnly : false;\n this.spellCheck = isBoolean(config.spellCheck) ? config.spellCheck : false;\n this.suffix = config.suffix ?? null;\n }\n}\n","import { DynamicInputControlModel, DynamicInputControlModelConfig } from \"../dynamic-input-control.model\";\nimport { DynamicFormControlLayout } from \"../misc/dynamic-form-control-layout.model\";\nimport { serializable } from \"../../decorator/serializable.decorator\";\nimport { isBoolean, isNumber } from \"../../utils/core.utils\";\nimport { Observable, isObservable, of } from \"rxjs\";\nimport { tap } from \"rxjs/operators\";\nimport { IConfig, initialConfig } from \"ngx-mask\";\n\nexport const DYNAMIC_FORM_CONTROL_TYPE_INPUT = \"INPUT\";\n\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_COLOR = \"color\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_DATE = \"date\";\n// export const DYNAMIC_FORM_CONTROL_INPUT_TYPE_DATETIME = \"datetime\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_DATETIME_LOCAL = \"datetime-local\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_EMAIL = \"email\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_FILE = \"file\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_MONTH = \"month\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_NUMBER = \"number\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_PASSWORD = \"password\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_RANGE = \"range\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_SEARCH = \"search\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_TEL = \"tel\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_TEXT = \"text\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_TIME = \"time\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_URL = \"url\";\nexport const DYNAMIC_FORM_CONTROL_INPUT_TYPE_WEEK = \"week\";\n\nexport interface DynamicInputModelConfig extends DynamicInputControlModelConfig<string | number | Date | string[]> {\n accept?: string;\n inputType?: string;\n list?: any[] | Observable<any[]>;\n mask?: string;\n maskConfig?: Partial<IConfig>;\n max?: number | string | Date;\n min?: number | string | Date;\n multiple?: boolean;\n pattern?: string;\n step?: number;\n}\n\nexport class DynamicInputModel extends DynamicInputControlModel<string | number | Date | string[]> {\n @serializable() accept: string | null;\n @serializable() inputType: string;\n files: FileList | null = null;\n list$: Observable<any[]> | null = null;\n @serializable() mask: string;\n @serializable() maskConfig: IConfig;\n @serializable() max: number | string | Date | null;\n @serializable() min: number | string | Date | null;\n @serializable() multiple: boolean | null;\n @serializable() pattern: string | null;\n @serializable() step: number | null;\n\n @serializable(\"list\") private _list: any[] | null = null;\n private readonly _listId: string | null = null;\n\n @serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_INPUT;\n\n constructor(config: DynamicInputModelConfig, layout?: DynamicFormControlLayout) {\n super(config, layout);\n\n this.accept = config.accept ?? null;\n this.inputType = config.inputType ?? DYNAMIC_FORM_CONTROL_INPUT_TYPE_TEXT;\n this.mask = config.mask ?? \"\";\n this.maskConfig = config.maskConfig ? {...initialConfig, ...config.maskConfig} : initialConfig;\n this.max = config.max !== undefined ? config.max : null;\n this.min = config.min !== undefined ? config.min : null;\n this.multiple = isBoolean(config.multiple) ? config.multiple : null;\n this.pattern = config.pattern ?? null;\n this.step = isNumber(config.step) ? config.step : null;\n\n if (config.list !== undefined) {\n this.list = config.list;\n this._listId = `${this.id}List`;\n }\n }\n\n get listId(): string | null {\n return this._listId;\n }\n\n get hasList(): boolean {\n return isObservable(this.list$);\n }\n\n set list(list: any[] | Observable<any[]> | null) {\n if (Array.isArray(list)) {\n this._list = list;\n this.list$ = of(this._list);\n\n } else if (isObservable(list)) {\n this.list$ = list.pipe(\n tap(_list => this._list = _list)\n );\n\n } else {\n this._list = null;\n this.list$ = null;\n }\n }\n}\n","import { Directive, Input, TemplateRef } from \"@angular/core\";\n\nexport enum DYNAMIC_TEMPLATE_DIRECTIVE_ALIGNMENT {\n Start = \"START\",\n End = \"END\"\n}\n\n@Directive({\n selector: \"ng-template[modelId],ng-template[modelType]\",\n standalone: true\n})\nexport class DynamicTemplateDirective {\n @Input() align: string = DYNAMIC_TEMPLATE_DIRECTIVE_ALIGNMENT.End;\n @Input() as: string | null = null;\n @Input() index?: number;\n @Input() modelId?: string;\n @Input() modelType?: string;\n\n constructor(public templateRef: TemplateRef<any>) {\n }\n}\n","import { Injectable, QueryList } from \"@angular/core\";\nimport {\n DynamicFormControlLayout,\n DynamicFormControlLayoutConfig,\n DynamicFormControlLayoutContext,\n DynamicFormControlLayoutPlace\n} from \"../model/misc/dynamic-form-control-layout.model\";\nimport { DynamicFormControlModel } from \"../model/dynamic-form-control.model\";\nimport { DynamicFormArrayGroupModel } from \"../model/form-array/dynamic-form-array.model\";\nimport { DynamicTemplateDirective, DYNAMIC_TEMPLATE_DIRECTIVE_ALIGNMENT } from \"../directive/dynamic-template.directive\";\nimport { isObject, isString } from \"../utils/core.utils\";\n\nexport type DynamicFormLayout = { [id: string]: DynamicFormControlLayout };\n\nexport type DynamicFormControlTemplates = QueryList<DynamicTemplateDirective> | DynamicTemplateDirective[] | undefined;\n\n@Injectable({\n providedIn: \"root\"\n})\nexport class DynamicFormLayoutService {\n\n findById(id: string, formLayout: DynamicFormLayout | null): DynamicFormControlLayout | null {\n if (isObject(formLayout)) {\n for (const key of Object.keys(formLayout)) {\n if (key === id) {\n return formLayout[key];\n }\n }\n }\n\n return null;\n }\n\n findByModel(model: DynamicFormControlModel, formLayout: DynamicFormLayout | null | undefined): DynamicFormControlLayout | null {\n let controlLayout: DynamicFormControlLayout | null = null;\n\n if (isObject(formLayout)) {\n for (const key of Object.keys(formLayout)) {\n key.split(\",\").forEach(substring => {\n const selector = substring.trim();\n\n if (selector === model.id || selector === model.type) {\n controlLayout = formLayout[key];\n }\n });\n }\n }\n\n return controlLayout;\n }\n\n filterTemplatesByModel(model: DynamicFormControlModel, templates: DynamicFormControlTemplates): DynamicTemplateDirective[] {\n const filterCallback: (template: DynamicTemplateDirective) => boolean = (template: DynamicTemplateDirective) => {\n return template.modelId === model.id || template.modelType === model.type;\n };\n\n if (templates instanceof QueryList) {\n return templates.filter(filterCallback);\n\n } else if (Array.isArray(templates)) {\n return templates.filter(filterCallback);\n }\n\n return [];\n }\n\n getAlignedTemplate(model: DynamicFormControlModel, templates: DynamicFormControlTemplates,\n alignment: DYNAMIC_TEMPLATE_DIRECTIVE_ALIGNMENT): DynamicTemplateDirective | undefined {\n\n return this.filterTemplatesByModel(model, templates)\n .find(template => template.as === null && template.align === alignment);\n }\n\n /*\n getIndexedTemplates(model: DynamicFormControlModel, templates: DynamicFormControlTemplates): DynamicTemplateDirective[] | undefined {\n return this.filterTemplatesByModel(model, templates).filter(template => template.as === null);\n }\n */\n getStartTemplate(model: DynamicFormControlModel, templates: DynamicFormControlTemplates): DynamicTemplateDirective | undefined {\n return this.getAlignedTemplate(model, templates, DYNAMIC_TEMPLATE_DIRECTIVE_ALIGNMENT.Start);\n }\n\n getEndTemplate(model: DynamicFormControlModel, templates: DynamicFormControlTemplates): DynamicTemplateDirective | undefined {\n return this.getAlignedTemplate(model, templates, DYNAMIC_TEMPLATE_DIRECTIVE_ALIGNMENT.End);\n }\n\n getClass(layout: DynamicFormControlLayout | null | undefined, context: DynamicFormControlLayoutContext,\n place: DynamicFormControlLayoutPlace): string {\n\n if (isObject(layout) && layout.hasOwnProperty(context)) {\n const config = layout[context] as DynamicFormControlLayoutConfig;\n if (config.hasOwnProperty(place)) {\n return config[place] as string;\n }\n }\n\n return \"\";\n }\n\n getHostClass(layout: DynamicFormControlLayout | null | undefined): string {\n const keys: (keyof DynamicFormControlLayout)[] = [\"element\", \"grid\"];\n let cls = \"\";\n\n if (isObject(layout)) {\n keys.forEach(key => {\n if (isObject(layout[key]) && isString(layout[key]?.host)) {\n cls = cls + ` ${layout[key]?.host}`;\n }\n });\n }\n\n return cls;\n }\n\n getElementId(model: DynamicFormControlModel): string {\n let id = model.id;\n let parent = model.parent;\n\n while (parent !== null) {\n if (parent instanceof DynamicFormArrayGroupModel) {\n id = `${parent.context.id}-${parent.index}-${model.id}`;\n break;\n }\n\n parent = parent.parent;\n }\n\n return id;\n }\n}\n","export interface DynamicValidatorDescriptor {\n name: string;\n args: any;\n}\n\nexport type DynamicValidatorsConfig = { [validatorKey: string]: any | DynamicValidatorDescriptor };\n\nexport enum DynamicFormHook {\n Blur = \"blur\",\n Change = \"change\",\n Submit = \"submit\"\n}\n","import { InjectionToken } from \"@angular/core\";\nimport { AsyncValidatorFn, ValidatorFn } from \"@angular/forms\";\n\nexport type Validator = ValidatorFn | AsyncValidatorFn;\n\nexport type ValidatorFactory = (args: any) => Validator;\n\nexport type ValidatorsToken = Validator[];\n\nexport type ValidatorsMap = Map<string, Validator | ValidatorFactory>;\n\nexport const DYNAMIC_VALIDATORS = new InjectionToken<ValidatorsMap>(\"DYNAMIC_VALIDATORS\");\n","import { InjectionToken } from \"@angular/core\";\nimport { AbstractControl } from \"@angular/forms\";\nimport { DynamicFormControlModel } from \"../model/dynamic-form-control.model\";\nimport { DynamicFormHook } from \"../model/misc/dynamic-form-control-validation.model\";\n\nexport type DynamicErrorMessagesMatcher = (control: AbstractControl, model: DynamicFormControlModel, hasFocus: boolean) => boolean;\n\nexport const DEFAULT_ERROR_STATE_MATCHER: DynamicErrorMessagesMatcher =\n (control: AbstractControl, model: DynamicFormControlModel, hasFocus: boolean) => {\n return control.touched && !hasFocus;\n };\n\nexport const CHANGE_ERROR_STATE_MATCHER: DynamicErrorMessagesMatcher =\n (control: AbstractControl, model: DynamicFormControlModel, hasFocus: boolean) => {\n return (model.updateOn === DynamicFormHook.Change || model.updateOn === null) ? control.dirty : control.touched && !hasFocus;\n };\n\nexport const DYNAMIC_ERROR_MESSAGES_MATCHER = new InjectionToken<DynamicErrorMessagesMatcher>(\"DYNAMIC_ERROR_MESSAGES_MATCHER\");\n","import { Injectable, Inject, Optional } from \"@angular/core\";\nimport {\n AbstractControl,\n AsyncValidatorFn,\n ValidatorFn,\n Validators,\n NG_VALIDATORS,\n NG_ASYNC_VALIDATORS\n} from \"@angular/forms\";\nimport { DynamicFormControlModel } from \"../model/dynamic-form-control.model\";\nimport {\n DynamicFormHook,\n DynamicValidatorDescriptor,\n DynamicValidatorsConfig\n} from \"../model/misc/dynamic-form-control-validation.model\";\nimport { isObject, isString } from \"../utils/core.utils\";\nimport { DYNAMIC_VALIDATORS, Validator, ValidatorFactory, ValidatorsToken } from \"./dynamic-form-validators\";\nimport {\n DEFAULT_ERROR_STATE_MATCHER,\n DYNAMIC_ERROR_MESSAGES_MATCHER,\n DynamicErrorMessagesMatcher\n} from \"./dynamic-form-validation-matchers\";\n\n@Injectable({\n providedIn: \"root\"\n})\nexport class DynamicFormValidationService {\n\n constructor(@Optional() @Inject(NG_VALIDATORS) private _NG_VALIDATORS: ValidatorFn[],\n @Optional() @Inject(NG_ASYNC_VALIDATORS) private _NG_ASYNC_VALIDATORS: AsyncValidatorFn[],\n @Optional() @Inject(DYNAMIC_VALIDATORS) private _DYNAMIC_VALIDATORS: Map<string, Validator | ValidatorFactory>,\n @Optional() @Inject(DYNAMIC_ERROR_MESSAGES_MATCHER) private _DYNAMIC_ERROR_MESSAGES_MATCHER: DynamicErrorMessagesMatcher) {\n }\n\n private getValidatorFn(validatorName: string, validatorArgs: any = null,\n validatorsToken: ValidatorsToken = this._NG_VALIDATORS): Validator | never {\n\n let validatorFn: ValidatorFactory | Validator | undefined;\n\n if (Validators.hasOwnProperty(validatorName)) { // Built-in Angular Validators\n validatorFn = (Validators as any)[validatorName];\n\n } else { // Custom Validators\n if (this._DYNAMIC_VALIDATORS && this._DYNAMIC_VALIDATORS.has(validatorName)) {\n validatorFn = this._DYNAMIC_VALIDATORS.get(validatorName);\n\n } else if (validatorsToken) {\n validatorFn = validatorsToken.find(validator => validator.name === validatorName);\n }\n }\n\n if (validatorFn === undefined) { // throw when no validator could be resolved\n throw new Error(\n `validator \"${validatorName}\" is not provided via NG_VALIDATORS, NG_ASYNC_VALIDATORS or DYNAMIC_FORM_VALIDATORS`);\n }\n\n if (validatorArgs !== null) {\n return (validatorFn as ValidatorFactory)(validatorArgs);\n }\n\n return validatorFn as Validator;\n }\n\n private getValidatorFns(validatorsConfig: DynamicValidatorsConfig,\n validatorsToken: ValidatorsToken = this._NG_VALIDATORS): Validator[] {\n\n let validatorFns: Validator[] = [];\n\n if (isObject(validatorsConfig)) {\n\n validatorFns = Object.keys(validatorsConfig).map(validatorConfigKey => {\n const validatorConfigValue = (validatorsConfig as DynamicValidatorsConfig)[validatorConfigKey];\n\n if (this.isValidatorDescriptor(validatorConfigValue)) {\n const descriptor = validatorConfigValue as DynamicValidatorDescriptor;\n\n return this.getValidatorFn(descriptor.name, descriptor.args, validatorsToken);\n }\n\n return this.getValidatorFn(validatorConfigKey, validatorConfigValue, validatorsToken);\n });\n }\n\n return validatorFns;\n }\n\n getValidator(validatorName: string, validatorArgs: any = null): ValidatorFn {\n return this.getValidatorFn(validatorName, validatorArgs) as ValidatorFn;\n }\n\n getAsyncValidator(validatorName: string, validatorArgs: any = null): AsyncValidatorFn {\n return this.getValidatorFn(validatorName, validatorArgs, this._NG_ASYNC_VALIDATORS) as AsyncValidatorFn;\n }\n\n getValidators(validatorsConfig: DynamicValidatorsConfig): ValidatorFn[] {\n return this.getValidatorFns(validatorsConfig) as ValidatorFn[];\n }\n\n getAsyncValidators(asyncValidatorsConfig: DynamicValidatorsConfig): AsyncValidatorFn[] {\n return this.getValidatorFns(asyncValidatorsConfig, this._NG_ASYNC_VALIDATORS) as AsyncValidatorFn[];\n }\n\n updateValidators(validatorsConfig: DynamicValidatorsConfig | null, control: AbstractControl,\n model: DynamicFormControlModel): void {\n\n model.validators = validatorsConfig;\n\n if (validatorsConfig === null) {\n control.clearValidators();\n\n } else {\n control.setValidators(this.getValidators(validatorsConfig));\n }\n\n control.updateValueAndValidity();\n }\n\n updateAsyncValidators(asyncValidatorsConfig: DynamicValidatorsConfig | null, control: AbstractControl,\n model: DynamicFormControlModel): void {\n\n model.asyncValidators = asyncValidatorsConfig;\n\n if (asyncValidatorsConfig === null) {\n control.clearAsyncValidators();\n\n } else {\n control.setAsyncValidators(this.getAsyncValidators(asyncValidatorsConfig));\n }\n\n control.updateValueAndValidity();\n }\n\n showErrorMessages(control: AbstractControl, model: DynamicFormControlModel, hasFocus: boolean): boolean {\n const precondition = control.invalid && model.hasErrorMessages;\n const matcher = this._DYNAMIC_ERROR_MESSAGES_MATCHER ? this._DYNAMIC_ERROR_MESSAGES_MATCHER(control, model, hasFocus) :\n DEFAULT_ERROR_STATE_MATCHER(control, model, hasFocus);\n\n return precondition && matcher;\n }\n\n parseErrorMessageConfig(template: string, model: DynamicFormControlModel, error: any = null): string {\n return template.replace(/{{\\s*(.+?)\\s*}}/mg, (_match: string, expression: string) => {\n let propertySource: any = model;\n let propertyName: string = expression;\n\n if (expression.indexOf(\"validator.\") >= 0 && error) {\n propertySource = error;\n propertyName = expression.replace(\"validator.\", \"\");\n