ng-dynamic-json-form
Version:
Generate Angular reactive form dynamically using JSON. Support conditional rendering and toggle of validators.
913 lines (860 loc) • 37.9 kB
TypeScript
import * as _angular_core from '@angular/core';
import { Type, TemplateRef, OnInit, ViewContainerRef, ElementRef, InjectionToken, Provider, ProviderToken } from '@angular/core';
import * as _angular_forms from '@angular/forms';
import { AbstractControl, AsyncValidatorFn, ValidatorFn, ControlValueAccessor, Validator, UntypedFormGroup, ValidationErrors } from '@angular/forms';
import { FactoryArg } from 'imask/esm/index';
import * as ng_dynamic_json_form from 'ng-dynamic-json-form';
import * as rxjs from 'rxjs';
import { Observable, BehaviorSubject, Subject } from 'rxjs';
interface ConditionsActionFunctions {
[key: string]: (c?: AbstractControl) => void;
}
declare enum ConditionsActionEnum {
'control.hidden' = "control.hidden",
'control.disabled' = "control.disabled",
'validator.required' = "validator.required",
'validator.requiredTrue' = "validator.requiredTrue",
'validator.min' = "validator.min",
'validator.max' = "validator.max",
'validator.minLength' = "validator.minLength",
'validator.maxLength' = "validator.maxLength",
'validator.email' = "validator.email",
'validator.pattern' = "validator.pattern"
}
type ConditionsOperator = '===' | '!==' | '>=' | '>' | '<=' | '<' | 'includes' | 'notIncludes';
type ConditionsStatementTuple = [any, ConditionsOperator, any];
type ConditionsGroup = {
[key in '&&' | '||']?: (ConditionsStatementTuple | ConditionsGroup)[];
};
type ConditionType = keyof typeof ConditionsActionEnum | (string & {});
type Conditions = {
[key in ConditionType]?: ConditionsGroup;
};
interface OptionItem {
label: string;
value?: any;
[key: string]: any;
}
interface OptionSourceConfig {
url: string;
method: 'GET' | 'POST';
headers?: {
[key: string]: string | string[];
};
body?: {
[key: string]: any;
};
mapData?: {
labelKey: string;
valueKeys?: string[];
contentPath?: string;
slice?: [number, number];
appendPosition?: 'after' | 'before';
};
trigger?: {
by: string;
body: {
[key: string]: string;
};
debounceTime?: number;
};
filter?: {
by: string;
conditions: ConditionsGroup;
debounceTime?: number;
};
}
interface FormControlOptions {
data?: OptionItem[];
src?: string | OptionSourceConfig;
srcAppendPosition?: 'after' | 'before';
autoSelectFirst?: boolean;
layout?: 'row' | 'column';
labelPosition?: 'before' | 'after';
containerClass?: string;
containerStyles?: string;
}
type FormControlType = 'checkbox' | 'date' | 'number' | 'password' | 'radio' | 'range' | 'select' | 'switch' | 'text' | 'textarea' | 'textMask' | (string & {});
interface FormLayout {
hostClass?: string;
hostStyles?: string;
labelClass?: string;
labelStyles?: string;
contentClass?: string;
contentStyles?: string;
formGroupStyles?: string;
formGroupClass?: string;
descriptionClass?: string;
descriptionStyles?: string;
inputAreaClass?: string;
inputAreaStyles?: string;
errorClass?: string;
errorStyles?: string;
/**Put description before or after input */
descriptionPosition?: 'before' | 'after';
/**Set to true to take control of label display on your own */
hideLabel?: boolean;
/**Enable expand/collapse of content. The default state will be determined by value provided */
contentCollapsible?: 'collapse' | 'expand';
/**Add `required` class to form label if there's validator named `required`.
* Default is true.
*/
autoAddRequiredClass?: boolean;
}
declare enum ValidatorsEnum {
required = "required",
requiredTrue = "requiredTrue",
min = "min",
max = "max",
minLength = "minLength",
maxLength = "maxLength",
email = "email",
pattern = "pattern"
}
interface ValidatorConfig {
name: keyof typeof ValidatorsEnum | (string & {});
value?: any;
/**Use {{value}} placeholder to display current value */
message?: string;
/**Flags for `pattern` validator. */
flags?: string;
}
interface FormControlConfig {
formControlName: string;
asyncValidators?: ValidatorConfig[];
conditions?: Conditions;
/**Provide to make this control as a `FormGroup` */
children?: FormControlConfig[];
description?: string;
/**
* The properties to bind to the target element or `Directive`
*/
props?: any;
/**Don't render the UI of this control if set to true. */
hidden?: boolean;
label?: string;
layout?: FormLayout;
inputMask?: FactoryArg;
options?: FormControlOptions;
/**Set this input to readonly, and will add a class `readonly` to the host element of this control */
readonly?: boolean;
type?: FormControlType;
value?: any;
validators?: ValidatorConfig[];
}
interface ConfigValidationErrors {
errors: string;
config?: Partial<FormControlConfig>;
}
type CustomAsyncValidators = {
[key: string]: AsyncValidatorFn | ((_: any) => AsyncValidatorFn);
};
type CustomComponents = {
[key: string]: Type<CustomControlComponent>;
};
declare abstract class CustomErrorMessage {
control: AbstractControl;
errorMessages: _angular_core.WritableSignal<string[]>;
}
type CustomErrorComponents = {
[key: string]: Type<CustomErrorMessage>;
};
declare abstract class CustomFormLabel {
collapsible: _angular_core.WritableSignal<boolean>;
expand: _angular_core.WritableSignal<boolean>;
label: _angular_core.WritableSignal<string | undefined>;
layout: _angular_core.WritableSignal<FormLayout | undefined>;
props: _angular_core.WritableSignal<any>;
}
type CustomLabelComponents = {
[key: string]: Type<CustomFormLabel>;
};
type CustomLabelTemplates = {
[key: string]: TemplateRef<any>;
};
type CustomTemplates = {
[key: string]: TemplateRef<any>;
};
type CustomValidators = {
[key: string]: ValidatorFn | ((_: any) => ValidatorFn);
};
interface FormDisplayValue {
keyMapped: any;
keyPreserved: any;
}
interface FormReadyState {
form: boolean;
options: boolean;
}
interface FormStatusFunctions {
setDirty: () => void;
setPristine: () => void;
setTouched: () => void;
setUntouched: () => void;
}
type UiComponents = {
[K in FormControlType]?: Type<CustomControlComponent>;
};
declare class CustomControlComponent implements ControlValueAccessor, Validator {
/**
* This control can be use to bind the UI of the custom component with the parent control.
* Use this if you don't want to rewrite/override every methods in the CVA manually.
*
* Assign it with instance of `AbstractControl`
*
* ```
* // FormControl
* override control = new FormControl('');
*
* // FormGroup
* override control = new FormGroup({
* controlA: new FormControl(...),
* controlB: new FormControl(...)
* });
* ```
*/
control?: AbstractControl;
hostForm: _angular_core.WritableSignal<UntypedFormGroup | undefined>;
data: _angular_core.WritableSignal<FormControlConfig | undefined>;
hideErrorMessage: _angular_core.WritableSignal<boolean | undefined>;
writeValue(obj: any): void;
registerOnChange(fn: any): void;
registerOnTouched(fn: any): void;
setDisabledState(isDisabled: boolean): void;
validate(control: AbstractControl<any, any>): ValidationErrors | null;
markAsDirty(): void;
markAsPristine(): void;
markAsTouched(): void;
markAsUntouched(): void;
setErrors(errors: ValidationErrors | null): void;
onOptionsGet(options: OptionItem[]): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<CustomControlComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<CustomControlComponent, "custom-control", never, {}, {}, never, never, true, never>;
}
declare class ControlLayoutDirective {
private el;
controlLayout: _angular_core.InputSignal<{
type?: "host" | "label" | "content" | "formGroup" | "description" | "inputArea" | "error";
layout?: FormControlConfig["layout"];
} | undefined>;
classNames: _angular_core.Signal<string[]>;
styleList: _angular_core.Signal<string[]>;
updateClass: _angular_core.EffectRef;
updateStyles: _angular_core.EffectRef;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ControlLayoutDirective, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ControlLayoutDirective, "[controlLayout]", never, { "controlLayout": { "alias": "controlLayout"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}
declare class HostIdDirective {
private el;
hostId: _angular_core.InputSignal<{
parentId?: string;
controlName?: string;
} | undefined>;
computedId: _angular_core.Signal<string | undefined>;
updateAttribute: _angular_core.EffectRef;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HostIdDirective, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<HostIdDirective, "[hostId]", never, { "hostId": { "alias": "hostId"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}
declare class ImaskValuePatchDirective {
private imask;
private isNumber;
constructor();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ImaskValuePatchDirective, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ImaskValuePatchDirective, "[imaskValuePatch]", never, {}, {}, never, never, true, never>;
}
declare class PropsBindingDirective {
private injectionTokens;
private injector;
private cd;
private el;
propsBinding: _angular_core.InputSignal<{
props: any;
key?: string;
omit?: string[];
}[]>;
validPropsData: _angular_core.Signal<{
props: any;
key?: string;
omit?: string[];
}[]>;
handlePropsGet: _angular_core.EffectRef;
private updateComponentProperty;
private hasProperty;
private isValidHtmlAttribute;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PropsBindingDirective, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<PropsBindingDirective, "[propsBinding]", never, { "propsBinding": { "alias": "propsBinding"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}
declare class TextareaAutHeightDirective implements OnInit {
private el;
autoResize: _angular_core.InputSignal<boolean>;
onInput(): void;
ngOnInit(): void;
private removeResizeProperty;
private setHeight;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TextareaAutHeightDirective, never>;
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TextareaAutHeightDirective, "[textareaAutoHeight]", never, { "autoResize": { "alias": "autoResize"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}
declare class ContentWrapperComponent implements OnInit {
private destroyRef;
private global;
private hostEventService;
readonly showErrorsOnTouched: boolean;
config: _angular_core.InputSignal<FormControlConfig | undefined>;
control: _angular_core.InputSignal<AbstractControl<any, any, any> | undefined>;
collapsibleState: _angular_core.InputSignal<"collapse" | "expand" | undefined>;
isDirty: _angular_core.WritableSignal<boolean>;
isTouched: _angular_core.WritableSignal<boolean>;
controlErrors: _angular_core.ResourceRef<_angular_forms.ValidationErrors | null>;
hideErrors: _angular_core.Signal<boolean | undefined>;
formControlName: _angular_core.Signal<string>;
description: _angular_core.Signal<string | undefined>;
descriptionPosition: _angular_core.Signal<"before" | "after" | undefined>;
label: _angular_core.Signal<string | undefined>;
layout: _angular_core.Signal<FormLayout | undefined>;
props: _angular_core.Signal<any>;
validators: _angular_core.Signal<ng_dynamic_json_form.ValidatorConfig[]>;
showLabel: _angular_core.Signal<boolean | "" | undefined>;
customErrorComponent: _angular_core.Signal<_angular_core.Type<ng_dynamic_json_form.CustomErrorMessage> | undefined>;
customErrorTemplate: _angular_core.Signal<_angular_core.TemplateRef<any> | null>;
customLabelComponent: _angular_core.Signal<_angular_core.Type<ng_dynamic_json_form.CustomFormLabel> | undefined>;
customLabelTemplate: _angular_core.Signal<_angular_core.TemplateRef<any> | undefined>;
renderErrorSection: _angular_core.Signal<boolean>;
showErrors: _angular_core.Signal<boolean>;
ngOnInit(): void;
updateControlStatus(): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContentWrapperComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ContentWrapperComponent, "content-wrapper", never, { "config": { "alias": "config"; "required": false; "isSignal": true; }; "control": { "alias": "control"; "required": false; "isSignal": true; }; "collapsibleState": { "alias": "collapsibleState"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
}
declare class FormControlComponent implements ControlValueAccessor, Validator {
private destroyRef;
private global;
private formReadyStateService;
private optionsDataService;
private readonly uiComponents;
private inputComponentRef;
private pendingValue;
private onChange;
private onTouched;
readonly loadingComponent: Type<any> | null;
readonly loadingTemplate: _angular_core.TemplateRef<any> | null;
readonly hostForm: _angular_forms.UntypedFormGroup | undefined;
readonly hideErrorMessage$: rxjs.BehaviorSubject<boolean | undefined>;
data: _angular_core.InputSignal<FormControlConfig | undefined>;
control: _angular_core.InputSignal<AbstractControl<any, any, any> | undefined>;
customComponent: _angular_core.InputSignal<Type<CustomControlComponent> | undefined>;
inputComponentAnchor: _angular_core.Signal<ViewContainerRef>;
loading: _angular_core.WritableSignal<boolean>;
inputType: _angular_core.Signal<(string & {}) | "checkbox" | "date" | "password" | "radio" | "range" | "select" | "switch" | "text" | "textarea" | "textMask">;
inputComponent: _angular_core.Signal<Type<CustomControlComponent>>;
customInputTemplate: _angular_core.Signal<_angular_core.TemplateRef<any> | null>;
optionsConfig: _angular_core.Signal<ng_dynamic_json_form.FormControlOptions | undefined>;
dynamicOptions: _angular_core.Signal<OptionItem[] | undefined>;
useCustomLoading: _angular_core.Signal<boolean>;
init: _angular_core.EffectRef;
handleOptionsFetched: _angular_core.EffectRef;
onFocusOut(): void;
writeValue(obj: any): void;
registerOnChange(fn: (_: any) => void): void;
registerOnTouched(fn: () => void): void;
setDisabledState?(isDisabled: boolean): void;
validate(control: AbstractControl<any, any>): ValidationErrors | null;
updateControlStatus(type: keyof FormStatusFunctions): void;
private getOptionsByFilterOrTrigger;
private initComponentInstance;
private setLoading;
private writeControlValue;
private syncControlErrors;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormControlComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FormControlComponent, "form-control", never, { "data": { "alias": "data"; "required": false; "isSignal": true; }; "control": { "alias": "control"; "required": false; "isSignal": true; }; "customComponent": { "alias": "customComponent"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}
declare class FormGroupComponent {
private el;
private globalVariableService;
readonly customComponents: ng_dynamic_json_form.CustomComponents | undefined;
configs: _angular_core.InputSignal<FormControlConfig[] | undefined>;
collapsibleState: _angular_core.InputSignal<"collapse" | "expand" | undefined>;
parentId: _angular_core.InputSignal<string | undefined>;
parentForm: _angular_core.InputSignal<UntypedFormGroup>;
rootClass: _angular_core.InputSignal<string | undefined>;
rootStyles: _angular_core.InputSignal<string | undefined>;
contentWrapperRefs: _angular_core.Signal<readonly ContentWrapperComponent[]>;
contentWrapperEl: _angular_core.Signal<ElementRef<any> | undefined>;
formGroupRefs: _angular_core.Signal<readonly FormGroupComponent[]>;
formControlRefs: _angular_core.Signal<readonly FormControlComponent[]>;
updateClassList: _angular_core.EffectRef;
updateStyleList: _angular_core.EffectRef;
updateStatus(type: keyof FormStatusFunctions): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormGroupComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FormGroupComponent, "form-group", never, { "configs": { "alias": "configs"; "required": false; "isSignal": true; }; "collapsibleState": { "alias": "collapsibleState"; "required": false; "isSignal": true; }; "parentId": { "alias": "parentId"; "required": false; "isSignal": true; }; "parentForm": { "alias": "parentForm"; "required": true; "isSignal": true; }; "rootClass": { "alias": "rootClass"; "required": false; "isSignal": true; }; "rootStyles": { "alias": "rootStyles"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}
declare class NgDynamicJsonFormComponent implements ControlValueAccessor, Validator {
private providerConfig;
private cd;
private el;
private injector;
private destroyRef;
private configValidationService;
private formGeneratorService;
private formConditionsService;
private formValueService;
private formReadyStateService;
private globalVariableService;
private optionsDataService;
private hostEventService;
private controlDirective;
/**
* Whether to allow the form to mark as dirty
* @description
* If false, then it will automatically set to pristine
* after each value changes.
*/
private allowFormDirty;
private globalVariablesInitialized;
private reset$;
private onTouched;
private onChangeFn;
private buildFormComplete;
configs: _angular_core.InputSignal<string | FormControlConfig[] | undefined>;
/**
* User defined custom components. Use `formControlName` as the key to map target component.
*
* @example
* // Config
* {
* ...
* "formControlName": "compA"
* }
*
* // TS
* components = {
* compA: YourComponentA,
* compB: YourComponentB,
* ...
* }
*/
customComponents: _angular_core.InputSignal<CustomComponents | undefined>;
/**
* Custom templates for input, using `formControlName` as the key.
* Use this if creating a custom component is way too much.
*
* The template variables available:
* - `control` The FormControl for this input
* - `data` The config for this input
*/
customTemplates: _angular_core.InputSignal<CustomTemplates | undefined>;
/**
* Functions to execute when conditions is met.
* @description
* - When there's condition met, the function with key that match will be called.
* - The function contains an optional argument, which is the control of where the conditions will affect to.
*/
conditionsActionFunctions: _angular_core.InputSignal<ConditionsActionFunctions | undefined>;
collapsibleState: _angular_core.InputSignal<"collapse" | "expand" | undefined>;
descriptionPosition: _angular_core.InputSignal<"before" | "after" | undefined>;
rootClass: _angular_core.InputSignal<string | undefined>;
rootStyles: _angular_core.InputSignal<string | undefined>;
hideErrorMessage: _angular_core.InputSignal<boolean | undefined>;
errorComponents: _angular_core.InputSignal<CustomErrorComponents | undefined>;
errorComponentDefault: _angular_core.InputSignal<Type<CustomErrorMessage> | undefined>;
errorTemplates: _angular_core.InputSignal<CustomTemplates | undefined>;
errorTemplateDefault: _angular_core.InputSignal<TemplateRef<any> | undefined>;
labelComponents: _angular_core.InputSignal<CustomLabelComponents | undefined>;
labelComponentDefault: _angular_core.InputSignal<Type<CustomFormLabel> | undefined>;
labelTemplates: _angular_core.InputSignal<CustomTemplates | undefined>;
labelTemplateDefault: _angular_core.InputSignal<TemplateRef<any> | undefined>;
loadingComponent: _angular_core.InputSignal<Type<any> | undefined>;
loadingTemplate: _angular_core.InputSignal<TemplateRef<any> | undefined>;
/**
* Custom observables for the options
* @description
* The observable with key that match with the `src` will be used.
*
* @example
* ```ts
* optionsSources = {
* 'getCountries': ...
* }
*
* config = {
* ...
* options: {
* ...
* src: 'getCountries'
* }
* }
* ```
*/
optionsSources: _angular_core.InputSignal<{
[key: string]: Observable<OptionItem[]>;
} | undefined>;
formGet: _angular_core.OutputEmitterRef<UntypedFormGroup>;
/**
* The value change event of the form, which trigger by the user
* (by checking click or keydown event)
*/
onChange: _angular_core.OutputEmitterRef<any>;
optionsLoaded: _angular_core.OutputEmitterRef<void>;
displayValue: _angular_core.OutputEmitterRef<FormDisplayValue>;
updateStatusFunctions: _angular_core.OutputEmitterRef<FormStatusFunctions>;
formGroupRef: _angular_core.Signal<FormGroupComponent | undefined>;
form: _angular_core.WritableSignal<UntypedFormGroup | undefined>;
configValidationResult: _angular_core.Signal<{
configs: FormControlConfig[] | null;
errors?: ng_dynamic_json_form.ConfigValidationErrors[];
} | undefined>;
buildForm: _angular_core.EffectRef;
handleOptionsReady: _angular_core.EffectRef;
handleHideErrorMessageValueChange: _angular_core.EffectRef;
constructor();
ngOnInit(): void;
ngOnDestroy(): void;
validate(): Observable<ValidationErrors | null>;
registerOnValidatorChange?(fn: () => void): void;
writeValue(obj: any): void;
registerOnChange(fn: any): void;
registerOnTouched(fn: any): void;
setDisabledState?(isDisabled: boolean): void;
private setupVariables;
private getControlDirective;
private setupListeners;
private reset;
private updateFormStatus;
private formValueChanges$;
/**
* Use getter function to make everything works fine,
* don't use computed signal
*/
private get formErrors();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgDynamicJsonFormComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgDynamicJsonFormComponent, "ng-dynamic-json-form", never, { "configs": { "alias": "configs"; "required": false; "isSignal": true; }; "customComponents": { "alias": "customComponents"; "required": false; "isSignal": true; }; "customTemplates": { "alias": "customTemplates"; "required": false; "isSignal": true; }; "conditionsActionFunctions": { "alias": "conditionsActionFunctions"; "required": false; "isSignal": true; }; "collapsibleState": { "alias": "collapsibleState"; "required": false; "isSignal": true; }; "descriptionPosition": { "alias": "descriptionPosition"; "required": false; "isSignal": true; }; "rootClass": { "alias": "rootClass"; "required": false; "isSignal": true; }; "rootStyles": { "alias": "rootStyles"; "required": false; "isSignal": true; }; "hideErrorMessage": { "alias": "hideErrorMessage"; "required": false; "isSignal": true; }; "errorComponents": { "alias": "errorComponents"; "required": false; "isSignal": true; }; "errorComponentDefault": { "alias": "errorComponentDefault"; "required": false; "isSignal": true; }; "errorTemplates": { "alias": "errorTemplates"; "required": false; "isSignal": true; }; "errorTemplateDefault": { "alias": "errorTemplateDefault"; "required": false; "isSignal": true; }; "labelComponents": { "alias": "labelComponents"; "required": false; "isSignal": true; }; "labelComponentDefault": { "alias": "labelComponentDefault"; "required": false; "isSignal": true; }; "labelTemplates": { "alias": "labelTemplates"; "required": false; "isSignal": true; }; "labelTemplateDefault": { "alias": "labelTemplateDefault"; "required": false; "isSignal": true; }; "loadingComponent": { "alias": "loadingComponent"; "required": false; "isSignal": true; }; "loadingTemplate": { "alias": "loadingTemplate"; "required": false; "isSignal": true; }; "optionsSources": { "alias": "optionsSources"; "required": false; "isSignal": true; }; }, { "formGet": "formGet"; "onChange": "onChange"; "optionsLoaded": "optionsLoaded"; "displayValue": "displayValue"; "updateStatusFunctions": "updateStatusFunctions"; }, never, never, true, never>;
}
interface FormConfig {
/**
* User defined custom validators. Use `name` as the key to map target ValidatorFn.
*
* Config:
* ```json
* {
* ...
* "validators": [
* { "name": "firstUppercase" }
* ]
* }
* ```
*
* TS:
* ```ts
* validators = {
* firstUppercase: firstUppercaseValidator,
* url: urlValidator,
* ...
* }
* ```
*
* HTML:
* ```html
* <ng-dynamic-json-form
* [configs]="..."
* [customValidators]="validators"
* ></ng-dynamic-json-form>
* ```
*/
customValidators?: CustomValidators;
/**
* User defined custom async validators. Similar to custom validators.
*
* Config:
* ```json
* {
* ...
* "asyncValidators": [
* ...
* ]
* }
* ```
*
* TS:
* ```ts
* asyncValidators = {
* ...
* }
* ```
*
* HTML:
* ```html
* <ng-dynamic-json-form
* [configs]="..."
* [customAsyncValidators]="validators"
* ></ng-dynamic-json-form>
* ```
*/
customAsyncValidators?: CustomAsyncValidators;
/**
* If the key is matched with `type` in the config, then the corresponding component will be used.
*
* ```ts
* config = {
* ...
* type: "file"
* }
*
* uiComponents = {
* file: InputFileComponent
* }
* ```
*/
uiComponents?: UiComponents;
/**
* Default validation message to use for the specific validator in the entire form.
*/
validationMessages?: {
[validatorName: string]: string;
};
/**
* Custom component for all labels in this form
*/
labelComponent?: Type<CustomFormLabel>;
/**
* Custom component for all loadings in this form
*/
loadingComponent?: Type<any>;
/**
* Custom component for all errors in this form
*/
errorComponent?: Type<CustomErrorMessage>;
/**
* Hide the error message for specific type of UI components
*/
hideErrorsForTypes?: FormControlType[];
showErrorsOnTouched?: boolean;
}
declare const NG_DYNAMIC_JSON_FORM_CONFIG: InjectionToken<FormConfig>;
declare function provideNgDynamicJsonForm(config?: FormConfig): Provider;
interface PropsBindingItem {
key: string;
token: ProviderToken<any>;
}
declare const PROPS_BINDING_INJECTORS: InjectionToken<PropsBindingItem[]>;
declare function providePropsBinding(value: PropsBindingItem[]): Provider;
declare class ConfigMappingService {
getCorrectedConfig(input: FormControlConfig): FormControlConfig;
private getFallbackValue;
private getFormControlName;
private mapInputMask;
private parseStringValue;
/**https://stackoverflow.com/questions/52869695/check-if-a-date-string-is-in-iso-and-utc-format */
private isIsoDate;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ConfigMappingService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<ConfigMappingService>;
}
declare class ConfigValidationService {
private configMappingService;
validateAndGetConfig(input: string | FormControlConfig[] | undefined): {
configs: FormControlConfig[] | null;
errors?: ConfigValidationErrors[];
};
private getBeautifyErrors;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ConfigValidationService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<ConfigValidationService>;
}
declare class FormConditionsService {
private globalVariableService;
private formValidationService;
private configsWithConditions;
/**Listen to the controls that specified in `conditions` to trigger the `targetControl` status and validators
* @param form The root form
* @param configs The JSON data
*/
listenConditions$(): Observable<any>;
executeConditions(): void;
private handleValueChanges;
private toggleControlStates;
private disableControl;
private hideControl$;
private toggleValidators;
private executeCustomActions;
/**Get the target element by using `id`(full control path) on each `div` inside current NgDynamicJsonForm instance */
private getTargetEl$;
private getPathsOfControlsToListen;
/**
* Get all the configs which has `conditions` set.
*
* @description
* The `fullControlPath` is the path to the control where the conditions will have effect on it.
*/
private extractConfigsWithConditions;
private evaluateConditionsStatement;
/**
* Get control path using the string in the conditions statement tuple.
*
* ```js
* form = new FormGroup{
* controlA: new FormControl(),
* controlB: new FormControl(),
* }
* ```
*
* - "controlA" => Should get "controlA"
* - "controlB" => Should get "controlB"
* - "controlA,prop1" => Should get "controlA"
* - "controlC" => undefined
*/
private getControlPathFromStatement;
/**Get the value from the statement, either it's literally a value or comes from a control
*
* ```js
* formValue = {
* controlA: 'textValue',
* controlB: false
* }
* ```
*
* - "controlA" => "textValue"
* - "controlB" => false
*/
private getValueFromStatement;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormConditionsService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<FormConditionsService>;
}
declare class FormGeneratorService {
private formValidationService;
generateFormGroup(data: FormControlConfig[]): UntypedFormGroup;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormGeneratorService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<FormGeneratorService>;
}
declare class FormReadyStateService {
private optionsLoadingCount;
optionsReady: _angular_core.WritableSignal<boolean>;
optionsLoading(add: boolean): void;
resetState(): void;
haveOptionsToWait(configs: FormControlConfig[]): boolean;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormReadyStateService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<FormReadyStateService>;
}
declare class FormValidationService {
private globalVariableService;
getErrorMessages$(control: AbstractControl | null | undefined, validators?: ValidatorConfig[]): Observable<string[]>;
getValidators(input: ValidatorConfig[] | undefined): ValidatorFn[];
getAsyncValidators(input: ValidatorConfig[] | undefined): AsyncValidatorFn[];
/**Get the error messages of the control
*
* @description
* Try to get the custom error message specified in the config first,
* else use the error message in the `ValidationErrors`.
*
* When using custom validator, the custom message most likely will not working,
* it's because we are using the key in the errors to find the config message.
* Since user can define the error object, it becomes very difficult to match the config name
* with the keys in the error object.
*/
private getErrorMessages;
private getConfigFromErrorKey;
private getValidatorValue;
/**
* Get validatorFn from either validatorFn or factory function that return a validatorFn.
* If it's a factory function, return the validatorFn instead.
*
* @param validatorConfig
* @param validatorFn
*/
private getValidatorFn;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormValidationService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<FormValidationService>;
}
declare class FormValueService {
patchForm(form: UntypedFormGroup | undefined, value: any): void;
getFormDisplayValue(value: any, configs: FormControlConfig[]): FormDisplayValue;
private getKeyPreservedDisplayValue;
private getKeyMappedFormDisplayValue;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormValueService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<FormValueService>;
}
interface GlobalVariables extends Omit<GlobalVariableService, 'setup' | 'rootConfigs' | 'rootForm' | 'hideErrorMessage$'> {
}
declare class GlobalVariableService {
descriptionPosition?: FormLayout['descriptionPosition'];
hideErrorMessage$: BehaviorSubject<boolean | undefined>;
rootConfigs: FormControlConfig[];
rootForm?: UntypedFormGroup;
showErrorsOnTouched: boolean;
hostElement?: HTMLElement;
conditionsActionFunctions: ConditionsActionFunctions | undefined;
optionsSources: {
[key: string]: Observable<OptionItem[]>;
} | undefined;
uiComponents: UiComponents | undefined;
customAsyncValidators: CustomAsyncValidators | undefined;
customValidators: CustomValidators | undefined;
customComponents: CustomComponents | undefined;
customTemplates: CustomTemplates | undefined;
errorComponents: CustomErrorComponents | undefined;
errorTemplates: CustomTemplates | undefined;
errorTemplateDefault: TemplateRef<any> | undefined;
errorComponentDefault: Type<CustomErrorMessage> | undefined;
labelComponents: CustomLabelComponents | undefined;
labelTemplates: CustomTemplates | undefined;
labelTemplateDefault: TemplateRef<any> | undefined;
labelComponentDefault: Type<CustomFormLabel> | undefined;
loadingComponent: Type<any> | undefined;
loadingTemplate: TemplateRef<any> | undefined;
hideErrorsForTypes: FormConfig['hideErrorsForTypes'];
validationMessages: FormConfig['validationMessages'];
setup(variables: GlobalVariables): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<GlobalVariableService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<GlobalVariableService>;
}
declare class HostEventService {
private platformId;
readonly focusOut$: Subject<FocusEvent>;
readonly keyUp$: Subject<KeyboardEvent>;
readonly keyDown$: Subject<KeyboardEvent>;
readonly pointerUp$: Subject<PointerEvent>;
readonly pointerDown$: Subject<PointerEvent>;
start$(hostElement: HTMLElement): Observable<any>;
private event$;
private get isServer();
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HostEventService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<HostEventService>;
}
interface RequestParams {
src: string;
method: 'POST' | 'GET';
headers?: any;
body?: any;
}
declare class HttpRequestCacheService {
private requests;
private http;
request$(params: RequestParams): Observable<Object>;
reset(): void;
private prevSameRequest;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HttpRequestCacheService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<HttpRequestCacheService>;
}
declare class OptionsDataService {
private globalVariableService;
private httpRequestCacheService;
private cancelAll$;
cancelAllRequest(): void;
onDestroy(): void;
getOptions$(srcConfig: OptionSourceConfig): Observable<OptionItem[]>;
getOptionsByFilter$(props: {
srcConfig: OptionSourceConfig;
valueChangeCallback: () => void;
finalizeCallback: () => void;
}): Observable<OptionItem[]>;
getOptionsOnTrigger$(props: {
srcConfig: OptionSourceConfig;
valueChangeCallback: () => void;
finalizeCallback: () => void;
}): Observable<OptionItem[]>;
/**The `valueChanges` of trigger control */
private onTriggerControlChanges$;
private mapData;
private getMappedSrc;
private mapBodyValue;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<OptionsDataService, never>;
static ɵprov: _angular_core.ɵɵInjectableDeclaration<OptionsDataService>;
}
export { ConditionsActionEnum, ConfigMappingService, ConfigValidationService, ControlLayoutDirective, CustomControlComponent, CustomErrorMessage, CustomFormLabel, FormConditionsService, FormGeneratorService, FormReadyStateService, FormValidationService, FormValueService, GlobalVariableService, HostEventService, HostIdDirective, HttpRequestCacheService, ImaskValuePatchDirective, NG_DYNAMIC_JSON_FORM_CONFIG, NgDynamicJsonFormComponent, OptionsDataService, PROPS_BINDING_INJECTORS, PropsBindingDirective, TextareaAutHeightDirective, ValidatorsEnum, provideNgDynamicJsonForm, providePropsBinding };
export type { ConditionType, Conditions, ConditionsActionFunctions, ConditionsGroup, ConditionsOperator, ConditionsStatementTuple, ConfigValidationErrors, CustomAsyncValidators, CustomComponents, CustomErrorComponents, CustomLabelComponents, CustomLabelTemplates, CustomTemplates, CustomValidators, FormConfig, FormControlConfig, FormControlOptions, FormControlType, FormDisplayValue, FormLayout, FormReadyState, FormStatusFunctions, OptionItem, OptionSourceConfig, UiComponents, ValidatorConfig };