UNPKG

@yyasinaslan/easyform

Version:
1 lines 90.2 kB
{"version":3,"file":"yyasinaslan-easyform.mjs","sources":["../../../projects/easy-form/src/lib/interfaces/advanced-control-types.ts","../../../projects/easy-form/src/lib/interfaces/basic-control-types.ts","../../../projects/easy-form/src/lib/easy-form-field.ts","../../../projects/easy-form/src/lib/easy-form-generator.ts","../../../projects/easy-form/src/lib/easy-form.ts","../../../projects/easy-form/src/lib/tokens/easy-form-config.ts","../../../projects/easy-form/src/lib/pipes/observe.ts","../../../projects/easy-form/src/lib/easy-form-control.ts","../../../projects/easy-form/src/lib/components/ef-errors/ef-errors.component.ts","../../../projects/easy-form/src/lib/components/ef-errors/ef-errors.component.html","../../../projects/easy-form/src/lib/helpers/component-helper.ts","../../../projects/easy-form/src/lib/directives/form-field.directive.ts","../../../projects/easy-form/src/lib/directives/bind-events.directive.ts","../../../projects/easy-form/src/lib/controls/ef-textarea/ef-textarea.component.ts","../../../projects/easy-form/src/lib/controls/ef-textarea/ef-textarea.component.html","../../../projects/easy-form/src/lib/controls/ef-select/ef-select.component.ts","../../../projects/easy-form/src/lib/controls/ef-select/ef-select.component.html","../../../projects/easy-form/src/lib/controls/ef-checkbox/ef-checkbox.component.ts","../../../projects/easy-form/src/lib/controls/ef-checkbox/ef-checkbox.component.html","../../../projects/easy-form/src/lib/controls/ef-radio/ef-radio.component.ts","../../../projects/easy-form/src/lib/controls/ef-radio/ef-radio.component.html","../../../projects/easy-form/src/lib/controls/ef-switch/ef-switch.component.ts","../../../projects/easy-form/src/lib/controls/ef-switch/ef-switch.component.html","../../../projects/easy-form/src/lib/controls/ef-text/ef-text.component.ts","../../../projects/easy-form/src/lib/controls/ef-text/ef-text.component.html","../../../projects/easy-form/src/lib/easy-form/easy-form.component.ts","../../../projects/easy-form/src/lib/easy-form/easy-form.component.html","../../../projects/easy-form/src/lib/directives/array-item-template.directive.ts","../../../projects/easy-form/src/lib/directives/array-wrapper-template.directive.ts","../../../projects/easy-form/src/lib/components/ef-form-array/ef-form-array.component.ts","../../../projects/easy-form/src/lib/components/ef-form-array/ef-form-array.component.html","../../../projects/easy-form/src/public-api.ts","../../../projects/easy-form/src/yyasinaslan-easyform.ts"],"sourcesContent":["export enum AdvancedControlTypes {\r\n // Form group\r\n Group = \"group\",\r\n\r\n // Form array\r\n Array = \"array\",\r\n\r\n // Form array with single control\r\n ArraySimple = \"arraySimple\",\r\n}\r\n","export enum BasicControlTypes {\r\n // Textbox\r\n Text = \"text\",\r\n\r\n // Textarea\r\n TextArea = \"textarea\",\r\n\r\n // Checkbox with label\r\n Checkbox = \"checkbox\",\r\n\r\n // Checkbox group\r\n CheckboxGroup = \"checkboxGroup\",\r\n\r\n // Radio group\r\n Radio = \"radio\",\r\n\r\n // Select\r\n Select = \"select\",\r\n Combobox = \"combobox\",\r\n Date = \"date\",\r\n Number = \"number\",\r\n Time = \"time\",\r\n DateTime = \"datetime\",\r\n\r\n // Switch with label\r\n Switch = \"switch\",\r\n}\r\n","import {FormFieldBase} from \"./interfaces/form-field\";\r\nimport {BasicControlTypes} from \"./interfaces/basic-control-types\";\r\nimport {AdvancedControlTypes} from \"./interfaces/advanced-control-types\";\r\nimport {Validation} from \"./interfaces/validation\";\r\nimport {ValidatorFn, Validators} from \"@angular/forms\";\r\nimport {ObservableString} from \"./interfaces/observable-string\";\r\nimport {SelectOptions} from \"./interfaces/select-options\";\r\nimport {FormSchema} from \"./interfaces/form-schema\";\r\n\r\n\r\nexport class EasyFormField<FormType = any> implements FormFieldBase<FormType> {\r\n\r\n // Optional field id\r\n id?: string;\r\n\r\n // Field label\r\n label?: ObservableString;\r\n\r\n // Hint\r\n hint?: string;\r\n\r\n /**\r\n * The type of control to be rendered\r\n */\r\n controlType: string | BasicControlTypes | AdvancedControlTypes = '';\r\n\r\n validations: Record<string, Validation> = {};\r\n\r\n props?: Record<string, any>;\r\n\r\n initialValue?: FormType;\r\n\r\n options?: SelectOptions<any>;\r\n\r\n // transformer?: {\r\n // toForm?: (value: RemoteType) => FormType;\r\n // fromForm?: (value: FormType) => RemoteType;\r\n // }\r\n\r\n // Child schema for array or group\r\n // schema?: EasyFormField<FormType> | Record<keyof FormType, EasyFormField>;\r\n schema?: EasyFormField<FormType> | FormSchema<FormType>;\r\n\r\n constructor(options: FormFieldBase<FormType>) {\r\n Object.assign(this, options);\r\n }\r\n\r\n /**\r\n * Add a required validation to the field\r\n * @param message\r\n */\r\n required(message: ObservableString) {\r\n if (this.validations && this.validations[\"required\"]) return this\r\n\r\n if (!this.validations) this.validations = {};\r\n\r\n this.validations[\"required\"] = {validator: Validators.required, message};\r\n\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Add a requiredTrue validation to the field\r\n * @param message\r\n */\r\n requiredTrue(message: ObservableString) {\r\n if (this.validations && this.validations[\"required\"]) return this\r\n\r\n if (!this.validations) this.validations = {};\r\n\r\n this.validations[\"required\"] = {validator: Validators.requiredTrue, message};\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Add a minLength validation to the field\r\n * @param minLength\r\n * @param message\r\n */\r\n minLength(minLength: number, message: ObservableString) {\r\n if (this.validations && this.validations[\"minlength\"]) return this;\r\n\r\n if (!this.validations) this.validations = {};\r\n\r\n this.validations[\"minlength\"] = {validator: Validators.minLength(minLength), message};\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Add a maxLength validation to the field\r\n * @param maxLength\r\n * @param message\r\n */\r\n maxLength(maxLength: number, message: ObservableString) {\r\n if (this.validations && this.validations[\"maxlength\"]) return this;\r\n\r\n if (!this.validations) this.validations = {};\r\n\r\n this.validations[\"maxlength\"] = {validator: Validators.maxLength(maxLength), message};\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Add an email validation to the field\r\n * @param message\r\n */\r\n email(message: ObservableString) {\r\n if (this.validations && this.validations[\"email\"]) return this;\r\n\r\n if (!this.validations) this.validations = {};\r\n\r\n this.validations[\"email\"] = {validator: Validators.email, message};\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Add a pattern validation to the field\r\n * @param pattern\r\n * @param message\r\n */\r\n pattern(pattern: string | RegExp, message: ObservableString) {\r\n if (this.validations && this.validations[\"pattern\"]) return this;\r\n\r\n if (!this.validations) this.validations = {};\r\n\r\n this.validations[\"pattern\"] = {validator: Validators.pattern(pattern), message};\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Add a min validation to the field\r\n * @param min\r\n * @param message\r\n */\r\n min(min: number, message: ObservableString) {\r\n if (this.validations && this.validations[\"min\"]) return this;\r\n\r\n if (!this.validations) this.validations = {};\r\n\r\n this.validations[\"min\"] = {validator: Validators.min(min), message};\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Add a max validation to the field\r\n * @param max\r\n * @param message\r\n */\r\n max(max: number, message: ObservableString) {\r\n if (this.validations && this.validations[\"max\"]) return this;\r\n\r\n if (!this.validations) this.validations = {};\r\n\r\n this.validations[\"max\"] = {validator: Validators.max(max), message};\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Add a custom validation to the field\r\n * @param validator\r\n * @param messages\r\n */\r\n customValidator(validator: ValidatorFn, messages: Record<string, ObservableString>) {\r\n if (!this.validations) this.validations = {};\r\n\r\n Object.keys(messages).forEach(key => {\r\n this.validations[key] = {validator, message: messages[key]};\r\n });\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Set the initial value of the field\r\n * @param value\r\n */\r\n default(value: FormType) {\r\n this.initialValue = value;\r\n return this;\r\n }\r\n\r\n /**\r\n * Transform the value\r\n * ! Not implemented yet\r\n * @param toForm\r\n * @notImplemented\r\n */\r\n // toForm(toForm: (value: RemoteType) => FormType) {\r\n // if (!this.transformer) this.transformer = {};\r\n // this.transformer.toForm = toForm;\r\n // return this;\r\n // }\r\n\r\n /**\r\n * Transform the value\r\n * ! Not implemented yet\r\n * @param fromForm\r\n * @notImplemented\r\n */\r\n // fromForm(fromForm: (value: FormType) => RemoteType) {\r\n // if (!this.transformer) this.transformer = {};\r\n // this.transformer.fromForm = fromForm;\r\n // return this;\r\n // }\r\n}\r\n","import {FormFieldBase,} from \"./interfaces/form-field\";\r\nimport {ValidatorFn} from \"@angular/forms\";\r\nimport {BasicControlTypes} from \"./interfaces/basic-control-types\";\r\nimport {AdvancedControlTypes} from \"./interfaces/advanced-control-types\";\r\nimport {EasyFormField} from \"./easy-form-field\";\r\nimport {ObservableString} from \"./interfaces/observable-string\";\r\nimport {SelectOptions} from \"./interfaces/select-options\";\r\nimport {FormSchema} from \"./interfaces/form-schema\";\r\n\r\ninterface EfDefaultValidations {\r\n required: (message: string) => FormFieldWithValidation;\r\n requiredTrue: (message: string) => FormFieldWithValidation;\r\n minLength: (minlength: number, message: string) => FormFieldWithValidation;\r\n maxLength: (length: number, message: string) => FormFieldWithValidation;\r\n email: (message: string) => FormFieldWithValidation;\r\n pattern: (pattern: string | RegExp, message: string) => FormFieldWithValidation;\r\n min: (min: number, message: string) => FormFieldWithValidation;\r\n max: (max: number, message: string) => FormFieldWithValidation;\r\n custom: (key: string, validator: ValidatorFn, message: string) => FormFieldWithValidation;\r\n}\r\n\r\ntype FormFieldWithValidation = FormFieldBase & EfDefaultValidations;\r\n\r\nexport type GeneratorBaseOptions = Omit<FormFieldBase, \"label\" | \"validations\">;\r\n\r\nexport abstract class EasyFormGenerator {\r\n\r\n public static text<ValueType = string>(value: ValueType, label?: ObservableString, configs?: GeneratorBaseOptions) {\r\n return new EasyFormField<ValueType>({...configs, label, initialValue: value, controlType: \"text\"});\r\n }\r\n\r\n public static textarea<ValueType = string>(value: ValueType, label?: ObservableString, configs?: GeneratorBaseOptions) {\r\n return new EasyFormField<ValueType>({...configs, label, initialValue: value, controlType: \"textarea\"});\r\n }\r\n\r\n public static select<ValueType = any>(value: ValueType, options: SelectOptions<any>, label?: ObservableString, configs?: GeneratorBaseOptions) {\r\n const vc = new EasyFormField<ValueType>({\r\n ...configs,\r\n label,\r\n initialValue: value,\r\n controlType: BasicControlTypes.Select\r\n });\r\n vc.options = options;\r\n return vc;\r\n }\r\n\r\n public static checkbox<ValueType = boolean>(value: ValueType, label?: ObservableString, configs?: GeneratorBaseOptions) {\r\n return new EasyFormField<ValueType>({\r\n ...configs,\r\n label,\r\n initialValue: value,\r\n controlType: BasicControlTypes.Checkbox\r\n });\r\n }\r\n\r\n public static switch<ValueType = any>(value: ValueType, label?: ObservableString, configs?: GeneratorBaseOptions) {\r\n return new EasyFormField<ValueType>({\r\n ...configs,\r\n label,\r\n initialValue: value,\r\n controlType: BasicControlTypes.Switch\r\n });\r\n }\r\n\r\n public static radio<ValueType = any>(value: ValueType, options: SelectOptions<any>, label?: ObservableString, configs?: GeneratorBaseOptions) {\r\n const vc = new EasyFormField<ValueType>({\r\n ...configs,\r\n label,\r\n initialValue: value,\r\n controlType: BasicControlTypes.Radio\r\n });\r\n vc.options = options;\r\n return vc;\r\n }\r\n\r\n public static custom<ValueType = any>(value: ValueType, type: string, label?: ObservableString, configs?: GeneratorBaseOptions) {\r\n return new EasyFormField<ValueType>({...configs, label, initialValue: value, controlType: type});\r\n }\r\n\r\n public static group<TValue>(schema: FormSchema<TValue>, configs?: GeneratorBaseOptions): EasyFormField<TValue> {\r\n return new EasyFormField<TValue>({\r\n ...configs,\r\n controlType: AdvancedControlTypes.Group,\r\n schema: schema\r\n });\r\n }\r\n\r\n public static array<TItem, TArray extends TItem[]>(schema: EasyFormField<TItem> | FormSchema<TItem>, configs?: GeneratorBaseOptions) {\r\n if (schema instanceof EasyFormField) {\r\n return new EasyFormField<TArray>({\r\n ...configs,\r\n controlType: AdvancedControlTypes.ArraySimple,\r\n schema: schema\r\n });\r\n }\r\n return new EasyFormField<TArray>({\r\n ...configs,\r\n controlType: AdvancedControlTypes.Array,\r\n schema: schema\r\n });\r\n }\r\n}\r\n","import {FormSchema} from \"./interfaces/form-schema\";\r\nimport {Validation} from \"./interfaces/validation\";\r\nimport {Signal} from \"@angular/core\";\r\nimport {Observable} from \"rxjs\";\r\nimport {FormArray, FormControl, FormGroup} from \"@angular/forms\";\r\nimport {BasicControlTypes} from \"./interfaces/basic-control-types\";\r\nimport {AdvancedControlTypes} from \"./interfaces/advanced-control-types\";\r\nimport {EasyFormGenerator} from \"./easy-form-generator\";\r\nimport {EasyFormControlComponent, LazyLoadingComponent} from \"./tokens/easy-form-config\";\r\nimport {EasyFormField} from \"./easy-form-field\";\r\n\r\nexport interface EasyFormOptions {\r\n showErrors?: 'submitted' | 'touched' | 'dirty' | 'always' | 'never';\r\n // Form based validations\r\n\r\n validations?: Record<string, Validation>;\r\n // Disabled state of the form\r\n\r\n disabled?: boolean | Signal<boolean> | Observable<boolean>;\r\n // Form field components\r\n\r\n components?: Record<string, EasyFormControlComponent | LazyLoadingComponent>\r\n}\r\n\r\nexport type InferValueType<Schema extends FormSchema> = { [key in keyof Schema]: Schema[key]['initialValue'] };\r\n\r\nexport class EasyForm<ValueType = any> extends EasyFormGenerator {\r\n\r\n /**\r\n * Reactivity of actual form is managed by angular reactive form\r\n */\r\n public formGroup: FormGroup;\r\n\r\n public schema!: FormSchema<ValueType>;\r\n // default options\r\n public options: EasyFormOptions = {\r\n showErrors: 'submitted',\r\n components: {}\r\n };\r\n\r\n constructor(schema: FormSchema<ValueType>, options?: EasyFormOptions) {\r\n super();\r\n this.schema = schema;\r\n this.options = {...this.options, ...options};\r\n this.formGroup = this.createFormGroup(this.schema);\r\n }\r\n\r\n get invalid() {\r\n return this.formGroup.invalid;\r\n }\r\n\r\n get valid() {\r\n return this.formGroup.valid;\r\n }\r\n\r\n get value(): ValueType {\r\n return this.formGroup.value;\r\n }\r\n\r\n get valueChanges(): Observable<ValueType> {\r\n return this.formGroup.valueChanges;\r\n }\r\n\r\n /**\r\n * Create a new instance of EasyForm\r\n * @param schema\r\n * @param options\r\n */\r\n public static create<T = any>(schema: FormSchema<T>, options?: EasyFormOptions) {\r\n return new EasyForm<T>(schema, options);\r\n }\r\n\r\n /**\r\n * Traverse through schema and get definition\r\n * @param path\r\n */\r\n getSchema(path: string | Array<string | number>) {\r\n const normalisedPath = typeof path == 'string' ? path.split('.') : path;\r\n if (!path || path.length == 0) {\r\n return null;\r\n }\r\n return this._getSchemaWithPath(normalisedPath, this.schema);\r\n }\r\n\r\n /**\r\n * Disable all form\r\n */\r\n disable() {\r\n this.formGroup.disable()\r\n }\r\n\r\n /**\r\n * Enable all form\r\n */\r\n enable() {\r\n this.formGroup.enable()\r\n }\r\n\r\n getComponentType(type: BasicControlTypes | string) {\r\n if (!this.options.components) {\r\n return null;\r\n }\r\n const c = this.options.components[type];\r\n if (!c) {\r\n return null;\r\n }\r\n return c;\r\n }\r\n\r\n getControl<ControlType = FormControl>(path: string | Array<string | number>) {\r\n return this.formGroup.get(path) as ControlType;\r\n }\r\n\r\n getArrayControls(path: string | Array<string | number>) {\r\n const arrayControl = this.getControl<FormArray>(path);\r\n if (!arrayControl) return [];\r\n return arrayControl.controls as FormControl[];\r\n }\r\n\r\n getValue<ValueType = any>(path?: string | Array<string | number>): ValueType {\r\n if (path) {\r\n return this.formGroup.get(path)?.value;\r\n }\r\n return this.formGroup.value;\r\n }\r\n\r\n getRawValue<ValueType = any>(path?: string | Array<string | number>): ValueType {\r\n if (path) {\r\n return this.formGroup.get(path)?.getRawValue();\r\n }\r\n return this.formGroup.getRawValue();\r\n }\r\n\r\n setValue(value: any, path?: string | Array<string | number>) {\r\n if (path) {\r\n this.formGroup.get(path)?.setValue(value);\r\n return;\r\n }\r\n this.formGroup.setValue(value);\r\n }\r\n\r\n patchValue(value: any, path?: string | Array<string | number>) {\r\n if (path) {\r\n this.formGroup.get(path)?.patchValue(value);\r\n return;\r\n }\r\n this.formGroup.patchValue(value);\r\n }\r\n\r\n addToArray(path: string, value: any) {\r\n const arr = this.formGroup.get(path) as FormArray;\r\n const schema = this.getSchema(path);\r\n if (!schema) {\r\n throw new Error(`Cannot find form schema for ${path}`);\r\n }\r\n if (!arr) {\r\n throw new Error(`Cannot find form array for ${path}`);\r\n }\r\n\r\n if (schema.controlType === AdvancedControlTypes.Array) {\r\n const g = this.createFormGroup(schema.schema as Record<string, EasyFormField>, value);\r\n arr.push(g);\r\n } else if (schema.controlType === AdvancedControlTypes.ArraySimple) {\r\n const arrayField = schema.schema as EasyFormField;\r\n const validations = arrayField.validations ?? {};\r\n const control = new FormControl(value, this.createValidations(validations));\r\n arr.push(control);\r\n }\r\n\r\n }\r\n\r\n removeFromArray(path: string, index: any) {\r\n const arr = this.formGroup.get(path) as FormArray;\r\n if (arr) {\r\n arr.removeAt(index)\r\n }\r\n }\r\n\r\n private createFormGroup(schema: FormSchema, initialValue?: any, validations?: EasyFormField['validations']): FormGroup {\r\n const group = new FormGroup({});\r\n\r\n for (const key in schema) {\r\n const field = schema[key];\r\n if (field.controlType == 'group') {\r\n const g = this.createFormGroup(field.schema as Record<string, EasyFormField>, field.initialValue, field.validations);\r\n group.addControl(key, g);\r\n } else if (field.controlType == 'array') {\r\n const a = this.createFormArray(field.schema as Record<string, EasyFormField>, field.initialValue, field.validations);\r\n group.addControl(key, a);\r\n } else if (field.controlType == 'arraySimple') {\r\n const a = this.createSimpleFormArray(field as any, field.initialValue, field.validations);\r\n group.addControl(key, a);\r\n } else {\r\n const control = new FormControl(field.initialValue, field.validations ? this.createValidations(field.validations) : []);\r\n group.addControl(key, control);\r\n }\r\n }\r\n\r\n if (validations) {\r\n group.addValidators(this.createValidations(validations));\r\n }\r\n\r\n if (initialValue) {\r\n group.patchValue(initialValue);\r\n }\r\n\r\n return group;\r\n }\r\n\r\n private createFormArray(schema: FormSchema, initialValue?: any, validations?: EasyFormField['validations']): FormArray {\r\n const array = new FormArray<any>([]);\r\n\r\n if (initialValue && Array.isArray(initialValue)) {\r\n initialValue.forEach((item: any) => {\r\n const group = this.createFormGroup(schema);\r\n group.patchValue(item);\r\n array.push(group);\r\n });\r\n }\r\n\r\n if (validations) {\r\n array.addValidators(this.createValidations(validations));\r\n }\r\n\r\n return array;\r\n }\r\n\r\n private createSimpleFormArray(schema: EasyFormField, initialValue?: any, validations?: EasyFormField['validations']): FormArray {\r\n const array = new FormArray<any>([]);\r\n const field = schema.schema as EasyFormField;\r\n\r\n if (initialValue && Array.isArray(initialValue)) {\r\n initialValue.forEach((item: any, index) => {\r\n const control = new FormControl(item, field.validations ? this.createValidations(field.validations) : []);\r\n array.push(control);\r\n });\r\n }\r\n\r\n if (validations) {\r\n array.addValidators(this.createValidations(validations));\r\n }\r\n\r\n return array;\r\n }\r\n\r\n private createValidations(validations: Record<string, Validation>) {\r\n const validators = [];\r\n if (validations) {\r\n for (const validationKey in validations) {\r\n const v = validations[validationKey];\r\n validators.push(v.validator);\r\n }\r\n }\r\n return validators;\r\n }\r\n\r\n private _getSchemaWithPath(path: (string | number)[], schema: FormSchema | EasyFormField): FormSchema | EasyFormField | null {\r\n const head = path[0];\r\n const tail = path.slice(1)\r\n\r\n const hasIndex = !!head.toString().match(/^[0-9]+/);\r\n if (hasIndex) {\r\n if (schema instanceof EasyFormField) {\r\n return schema ?? null;\r\n } else {\r\n if (tail.length == 0) {\r\n return schema ?? null;\r\n } else {\r\n return this._getSchemaWithPath(tail, schema);\r\n }\r\n }\r\n }\r\n\r\n\r\n if (schema instanceof EasyFormField) {\r\n return schema.schema ?? null;\r\n }\r\n\r\n const childSchema = (schema as Record<string, EasyFormField>)[head.toString()];\r\n if (childSchema) {\r\n if (tail.length == 0) {\r\n return childSchema;\r\n } else {\r\n return this._getSchemaWithPath(tail, childSchema.schema ?? {});\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n","import {InjectionToken} from \"@angular/core\";\r\nimport {ComponentType} from \"../interfaces/component-type\";\r\nimport {EasyFormControl} from \"../easy-form-control\";\r\n\r\nexport type EasyFormControlComponent = ComponentType<EasyFormControl>;\r\nexport type LazyLoadingComponent = () => Promise<any | EasyFormControlComponent>;\r\n\r\nexport interface EasyFormConfig {\r\n // Custom form control components to be used in the form\r\n controls: Record<string, EasyFormControlComponent | LazyLoadingComponent>;\r\n}\r\n\r\nconst EASY_FORM_CONFIG_TOKEN = 'EASY_FORM_CONFIG_TOKEN';\r\nexport const EASY_FORM_CONFIG = new InjectionToken<EasyFormConfig>(EASY_FORM_CONFIG_TOKEN);\r\n","import {isObservable, Observable} from \"rxjs\";\r\nimport {ChangeDetectorRef, inject, OnDestroy, Pipe, PipeTransform} from \"@angular/core\";\r\nimport {AsyncPipe} from \"@angular/common\";\r\n\r\n\r\n/**\r\n * Observe both Observable and Signal values\r\n */\r\n@Pipe({\r\n name: 'observe',\r\n pure: false,\r\n standalone: true\r\n})\r\nexport class ObservePipe<T> implements PipeTransform, OnDestroy {\r\n private cdr = inject(ChangeDetectorRef);\r\n\r\n private asyncPipe: AsyncPipe;\r\n\r\n constructor() {\r\n this.asyncPipe = new AsyncPipe(this.cdr);\r\n }\r\n\r\n transform(value: T | Observable<T> | undefined | null): T | null {\r\n if (value === undefined) return null;\r\n\r\n if (isObservable(value)) {\r\n return this.asyncPipe.transform(value);\r\n }\r\n\r\n return value;\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.asyncPipe.ngOnDestroy();\r\n }\r\n\r\n}\r\n","import {FormControl} from \"@angular/forms\";\r\nimport {computed, signal} from \"@angular/core\";\r\nimport {EasyFormField} from \"./easy-form-field\";\r\nimport {takeUntilDestroyed, toObservable} from \"@angular/core/rxjs-interop\";\r\nimport {of, switchMap} from \"rxjs\";\r\n\r\n\r\nexport interface EfControlData {\r\n id: string | null;\r\n control: FormControl<any> | null;\r\n schema: EasyFormField | null;\r\n // formFieldDirective: FormFieldDirective | null;\r\n}\r\n\r\n/**\r\n * Every form control should extend this class\r\n * to work with EasyFormComponent\r\n */\r\nexport class EasyFormControl {\r\n\r\n easyFormControl = signal<EfControlData>({\r\n id: null,\r\n control: null,\r\n schema: null,\r\n // formFieldDirective: null\r\n });\r\n\r\n control = computed(() => this.easyFormControl().control);\r\n\r\n schema = computed(() => this.easyFormControl().schema);\r\n\r\n // formFieldDirective = computed(() => this.easyFormControl().formFieldDirective);\r\n\r\n options = computed(() => {\r\n return this.schema()?.options;\r\n })\r\n\r\n props = signal<Record<string, any>>({});\r\n\r\n hasControl = computed(() => this.easyFormControl().control !== null);\r\n\r\n hasInitialized = computed(() => {\r\n const efData = this.easyFormControl();\r\n return efData.control !== null && efData.schema !== null;\r\n });\r\n\r\n value = toObservable(this.control)\r\n .pipe(takeUntilDestroyed(), switchMap(control => control ? control.valueChanges : of(null)))\r\n\r\n\r\n setValue(value: any) {\r\n this.control()?.setValue(value);\r\n }\r\n\r\n /**\r\n * Emit events\r\n * Usage: (input)=\"emitEvent($event)\"\r\n * @param event\r\n */\r\n emitEvent = (event: Event) => {\r\n // const directive = this.formFieldDirective;\r\n // if (directive && directive.fieldEvent && directive.fieldEvent instanceof EventEmitter) {\r\n // // Check if there are any subscribers to the event\r\n // if (directive.fieldEvent.observed) {\r\n // directive.fieldEvent.emit(event);\r\n // }\r\n // }\r\n }\r\n}\r\n","import {Component, ContentChild, Input, TemplateRef} from '@angular/core';\r\nimport {FormControl} from \"@angular/forms\";\r\nimport {KeyValuePipe, NgTemplateOutlet} from \"@angular/common\";\r\nimport {ObservePipe} from \"../../pipes/observe\";\r\nimport {EasyForm} from \"../../easy-form\";\r\nimport {EasyFormField} from \"../../easy-form-field\";\r\n\r\n@Component({\r\n selector: 'ef-errors',\r\n standalone: true,\r\n imports: [\r\n ObservePipe,\r\n NgTemplateOutlet,\r\n KeyValuePipe\r\n ],\r\n templateUrl: './ef-errors.component.html',\r\n styleUrl: './ef-errors.component.scss'\r\n})\r\nexport class EfErrorsComponent {\r\n @ContentChild('messageTemplate', {read: TemplateRef}) messageTemplate?: TemplateRef<{ $implicit: string }>;\r\n\r\n @Input() form?: EasyForm;\r\n @Input() path?: string | (number | string)[];\r\n @Input() control?: FormControl;\r\n @Input() formField?: EasyFormField;\r\n\r\n get _control() {\r\n if (this.control) return this.control;\r\n if (!this.path || !this.form) throw new Error('Path and form inputs are required');\r\n return this.form.getControl(this.path);\r\n }\r\n\r\n get _formField() {\r\n if (this.formField) return this.formField;\r\n if (!this.path || !this.form) throw new Error('Path and form inputs are required');\r\n return this.form.getSchema(this.path) as EasyFormField;\r\n }\r\n\r\n}\r\n","<ng-template #defaultErrorMessage let-message>\r\n @if (message) {\r\n <div class=\"ef-errors\">{{ message | observe }}</div>\r\n }\r\n</ng-template>\r\n\r\n@if (_control && _formField && _formField.validations) {\r\n @for (validation of (_formField.validations | keyvalue); track validation.key) {\r\n @if (_control.hasError(validation.key)) {\r\n <ng-container [ngTemplateOutlet]=\"messageTemplate ?? defaultErrorMessage\"\r\n [ngTemplateOutletContext]=\"{$implicit: validation.value.message}\"/>\r\n }\r\n }\r\n}\r\n","export function isComponent(component: unknown) {\r\n return (component as any).hasOwnProperty('ɵcmp');\r\n}\r\n","import {\r\n ComponentRef,\r\n DestroyRef,\r\n Directive,\r\n EventEmitter,\r\n inject,\r\n Injector,\r\n Input,\r\n OnChanges,\r\n Output,\r\n SimpleChanges,\r\n ViewContainerRef\r\n} from '@angular/core';\r\nimport {FormControl} from \"@angular/forms\";\r\nimport {EasyFormComponent} from \"../easy-form/easy-form.component\";\r\nimport {EasyFormControl} from \"../easy-form-control\";\r\nimport {isComponent} from \"../helpers/component-helper\";\r\nimport {EasyFormControlComponent, LazyLoadingComponent} from \"../tokens/easy-form-config\";\r\nimport {filter, Observable, Subscription} from \"rxjs\";\r\nimport {takeUntilDestroyed} from \"@angular/core/rxjs-interop\";\r\nimport {EasyFormField} from \"../easy-form-field\";\r\n\r\n@Directive({\r\n selector: 'ng-container[easyFormField]',\r\n standalone: true,\r\n exportAs: 'easyFormField',\r\n})\r\nexport class FormFieldDirective implements OnChanges {\r\n destroyRef = inject(DestroyRef)\r\n viewContainerRef = inject(ViewContainerRef)\r\n easyFormComponent = inject(EasyFormComponent)\r\n\r\n @Input() disabled = false;\r\n @Input() props?: Record<string, any>;\r\n // It emits control value changes\r\n @Output() change = new EventEmitter<any>();\r\n // Emit all events\r\n @Output() fieldEvent = new EventEmitter<Event>();\r\n // Filter events\r\n @Output(\"focus\") focus = this.fieldEvent.pipe(filter(e => e.type == 'focus' || e.type == 'focusin')) as Observable<FocusEvent>;\r\n @Output(\"blur\") blur = this.fieldEvent.pipe(filter(e => e.type == 'blur' || e.type == 'focusout')) as Observable<FocusEvent>;\r\n // Event emitters derived from fieldEvent\r\n @Output(\"input\") input = this.fieldEvent.pipe(filter(e => e.type == 'input')) as Observable<InputEvent>;\r\n @Output(\"keyup\") keyup = this.fieldEvent.pipe(filter(e => e.type == 'keyup')) as Observable<KeyboardEvent>;\r\n @Output(\"keydown\") keydown = this.fieldEvent.pipe(filter(e => e.type == 'keydown')) as Observable<KeyboardEvent>;\r\n\r\n public instance?: EasyFormControl;\r\n\r\n @Input({\r\n required: true,\r\n transform: (val: string | Array<string | number>): Array<string | number> => {\r\n const path = val;\r\n if (typeof path === 'string') {\r\n return path.split('.');\r\n }\r\n return path;\r\n }\r\n }) path!: Array<string | number>;\r\n\r\n control?: FormControl;\r\n\r\n private componentRef?: ComponentRef<EasyFormControl>;\r\n private valueChangeSubscription?: Subscription;\r\n\r\n get value() {\r\n return this.control?.value;\r\n }\r\n\r\n private get form() {\r\n return this.easyFormComponent.form;\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['path']) {\r\n this.pathChanged();\r\n }\r\n\r\n if (changes['disabled']) {\r\n const control = this.control;\r\n if (control) {\r\n if (this.disabled) {\r\n control.disable();\r\n } else {\r\n control.enable();\r\n }\r\n }\r\n }\r\n\r\n if (changes['props'] && this.componentRef) {\r\n this.componentRef.instance.props.set(changes['props'].currentValue);\r\n this.componentRef.changeDetectorRef.detectChanges();\r\n }\r\n }\r\n\r\n private pathChanged() {\r\n const control = this.setControl();\r\n if (control) {\r\n if (this.valueChangeSubscription) {\r\n this.valueChangeSubscription.unsubscribe();\r\n }\r\n this.control = control;\r\n this.valueChangeSubscription = control.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {\r\n this.change.emit(value);\r\n });\r\n\r\n this.render();\r\n }\r\n }\r\n\r\n private setControl() {\r\n const path = this.path;\r\n if (!path || path.length === 0) {\r\n return;\r\n }\r\n\r\n if (!this.easyFormComponent.form) {\r\n return undefined;\r\n }\r\n\r\n const control = this.easyFormComponent.form.getControl(path);\r\n\r\n if (!control) {\r\n return undefined;\r\n }\r\n return control as FormControl;\r\n }\r\n\r\n private async render() {\r\n await this._render();\r\n\r\n const control = this.control;\r\n if (control) {\r\n setTimeout(() => {\r\n if (this.disabled) {\r\n control.disable();\r\n } else {\r\n control.enable();\r\n }\r\n })\r\n }\r\n }\r\n\r\n private async _render() {\r\n const path = this.path;\r\n if (!path) {\r\n return;\r\n }\r\n const schema = this.form.getSchema(path);\r\n if (!schema) {\r\n throw new Error(`Path not found for ${path}`);\r\n }\r\n let componentDefinition = typeof schema.controlType === 'string' ? this.form.getComponentType(schema.controlType) : schema.controlType;\r\n let component: EasyFormControlComponent;\r\n if (!componentDefinition) {\r\n // Get component from formConfig\r\n componentDefinition = this.easyFormComponent.getComponentType(schema.controlType as string);\r\n }\r\n\r\n if (!componentDefinition) {\r\n throw new Error(`Component configuration not found for ${schema.controlType}`);\r\n }\r\n\r\n if (!isComponent(componentDefinition)) {\r\n // Assume this is lazy loading component\r\n if (typeof componentDefinition !== 'function') {\r\n throw new Error(`${schema.controlType} is not a valid Angular component`);\r\n }\r\n const lazyLoadingComponent = componentDefinition as LazyLoadingComponent;\r\n const loaded = await lazyLoadingComponent() as any;\r\n if (loaded.default) {\r\n component = loaded.default;\r\n } else if (typeof loaded === 'function' && isComponent(loaded)) {\r\n component = loaded as EasyFormControlComponent;\r\n } else {\r\n throw new Error(`${schema.controlType} has no default export or is not a valid Angular component`);\r\n }\r\n } else {\r\n component = componentDefinition as EasyFormControlComponent;\r\n }\r\n\r\n // Double check if component is a valid Angular component\r\n if (!isComponent(component)) {\r\n throw new Error(`${schema.controlType} is not a valid Angular component. Please provide a valid Angular component for ${schema.controlType} on provider EasyFormConfig`);\r\n }\r\n // Forwards this instance to the child component\r\n const injector = Injector.create({\r\n parent: this.viewContainerRef.injector,\r\n providers: [\r\n {\r\n provide: FormFieldDirective,\r\n useValue: this\r\n }\r\n ]\r\n })\r\n this.viewContainerRef.clear();\r\n if (this.componentRef) {\r\n this.componentRef.destroy();\r\n }\r\n const componentRef = this.viewContainerRef.createComponent<EasyFormControl>(component as EasyFormControlComponent, {\r\n injector: injector\r\n });\r\n this.componentRef = componentRef;\r\n this.instance = componentRef.instance;\r\n\r\n // This usage is removed in favor of directives props input\r\n // if (schema.props) {\r\n // // Initialize props\r\n // this.instance.props.set(schema.props);\r\n // }\r\n\r\n // Set component specific properties\r\n if (this.props) {\r\n this.componentRef.instance.props.set(this.props);\r\n }\r\n\r\n componentRef.instance.easyFormControl.set({\r\n id: path.join('_') + '_' + Math.random().toString(36).substring(2),\r\n control: this.control!,\r\n schema: schema as EasyFormField\r\n });\r\n\r\n componentRef.changeDetectorRef.detectChanges();\r\n }\r\n\r\n}\r\n","import {Directive, EventEmitter, HostListener, inject} from '@angular/core';\r\nimport {FormFieldDirective} from \"./form-field.directive\";\r\n\r\n/**\r\n * Bind events to input, textarea, select elements and emit events to the parent form field directive\r\n */\r\n@Directive({\r\n selector: 'input[bindEvents], textarea[bindEvents], select[bindEvents]',\r\n standalone: true\r\n})\r\nexport class BindEventsDirective {\r\n formFieldDirective = inject(FormFieldDirective, {skipSelf: true});\r\n\r\n @HostListener('input', ['$event']) onInput(event: Event) {\r\n this.emitEvent(event);\r\n }\r\n\r\n @HostListener('focus', ['$event']) onFocus(event: Event) {\r\n this.emitEvent(event);\r\n }\r\n\r\n @HostListener('blur', ['$event']) onBlur(event: Event) {\r\n this.emitEvent(event);\r\n }\r\n\r\n @HostListener('keyup', ['$event']) onKeyup(event: Event) {\r\n this.emitEvent(event);\r\n }\r\n\r\n @HostListener('keydown', ['$event']) onKeydown(event: Event) {\r\n this.emitEvent(event);\r\n }\r\n\r\n emitEvent = (event: Event) => {\r\n const directive = this.formFieldDirective;\r\n if (directive.fieldEvent && directive.fieldEvent instanceof EventEmitter) {\r\n // Check if there are any subscribers to the event\r\n if (directive.fieldEvent.observed) {\r\n directive.fieldEvent.emit(event);\r\n }\r\n }\r\n }\r\n\r\n}\r\n","import {Component} from '@angular/core';\r\nimport {ReactiveFormsModule} from \"@angular/forms\";\r\nimport {ObservePipe} from \"../../pipes/observe\";\r\nimport {EasyFormControl} from \"../../easy-form-control\";\r\nimport {EfErrorsComponent} from \"../../components/ef-errors/ef-errors.component\";\r\nimport {BindEventsDirective} from \"../../directives/bind-events.directive\";\r\n\r\n@Component({\r\n selector: 'ef-text',\r\n standalone: true,\r\n imports: [\r\n ReactiveFormsModule,\r\n ObservePipe,\r\n EfErrorsComponent,\r\n BindEventsDirective\r\n ],\r\n templateUrl: './ef-textarea.component.html',\r\n styleUrl: './ef-textarea.component.scss'\r\n})\r\nexport class EfTextAreaComponent extends EasyFormControl {\r\n}\r\n","@if (hasInitialized()) {\r\n @if (easyFormControl().schema!.label) {\r\n <label class=\"ef-form-label\" [for]=\"easyFormControl().id\">{{ easyFormControl().schema!.label | observe }}</label>\r\n }\r\n <textarea bindEvents [id]=\"easyFormControl().id\" [formControl]=\"easyFormControl().control!\"\r\n class=\"ef-input-textarea\">\r\n </textarea>\r\n <ef-errors [control]=\"easyFormControl().control!\" [formField]=\"easyFormControl().schema!\"/>\r\n}\r\n","import {Component} from '@angular/core';\r\nimport {FormsModule, ReactiveFormsModule} from \"@angular/forms\";\r\nimport {ObservePipe} from \"../../pipes/observe\";\r\nimport {EasyFormControl} from \"../../easy-form-control\";\r\nimport {EfErrorsComponent} from \"../../components/ef-errors/ef-errors.component\";\r\nimport {BindEventsDirective} from \"../../directives/bind-events.directive\";\r\n\r\n@Component({\r\n selector: 'ef-select',\r\n standalone: true,\r\n imports: [\r\n ReactiveFormsModule,\r\n ObservePipe,\r\n EfErrorsComponent,\r\n BindEventsDirective\r\n ],\r\n templateUrl: './ef-select.component.html',\r\n styleUrl: './ef-select.component.scss'\r\n})\r\nexport class EfSelectComponent extends EasyFormControl {\r\n}\r\n","@if (hasInitialized()) {\r\n @if (schema()!.label) {\r\n <label class=\"ef-form-label\" [for]=\"easyFormControl().id\">{{ easyFormControl().schema?.label | observe }}</label>\r\n }\r\n <select bindEvents [id]=\"easyFormControl().id\" [formControl]=\"easyFormControl().control!\"\r\n class=\"ef-input-select\">\r\n @if (easyFormControl().schema?.options) {\r\n @for (item of (easyFormControl().schema?.options | observe); track item.value) {\r\n <option [value]=\"item.value\">{{ item.label | observe }}</option>\r\n }\r\n }\r\n </select>\r\n <ef-errors [control]=\"easyFormControl().control!\" [formField]=\"easyFormControl().schema!\"/>\r\n}\r\n","import {Component} from '@angular/core';\r\nimport {ReactiveFormsModule} from \"@angular/forms\";\r\nimport {ObservePipe} from \"../../pipes/observe\";\r\nimport {EasyFormControl} from \"../../easy-form-control\";\r\nimport {EfErrorsComponent} from \"../../components/ef-errors/ef-errors.component\";\r\nimport {BindEventsDirective} from \"../../directives/bind-events.directive\";\r\n\r\n@Component({\r\n selector: 'ef-checkbox',\r\n standalone: true,\r\n imports: [\r\n ReactiveFormsModule,\r\n ObservePipe,\r\n EfErrorsComponent,\r\n BindEventsDirective\r\n ],\r\n templateUrl: './ef-checkbox.component.html',\r\n styleUrl: './ef-checkbox.component.scss'\r\n})\r\nexport class EfCheckboxComponent extends EasyFormControl {\r\n}\r\n","@if (hasInitialized()) {\r\n <input type=\"checkbox\" bindEvents [formControl]=\"easyFormControl().control!\" [id]=\"easyFormControl().id\">\r\n @if (easyFormControl().schema?.label) {\r\n <label class=\"ef-form-label\" [for]=\"easyFormControl().id\">{{ easyFormControl().schema?.label | observe }}</label>\r\n }\r\n <ef-errors [control]=\"easyFormControl().control!\" [formField]=\"easyFormControl().schema!\"/>\r\n}\r\n","import {Component} from '@angular/core';\r\nimport {ObservePipe} from \"../../pipes/observe\";\r\nimport {ReactiveFormsModule} from \"@angular/forms\";\r\nimport {EasyFormControl} from \"../../easy-form-control\";\r\nimport {EfErrorsComponent} from \"../../components/ef-errors/ef-errors.component\";\r\nimport {BindEventsDirective} from \"../../directives/bind-events.directive\";\r\n\r\n@Component({\r\n selector: 'lib-ef-radio',\r\n standalone: true,\r\n imports: [\r\n ObservePipe,\r\n ReactiveFormsModule,\r\n EfErrorsComponent,\r\n BindEventsDirective\r\n ],\r\n templateUrl: './ef-radio.component.html',\r\n styleUrl: './ef-radio.component.scss'\r\n})\r\nexport class EfRadioComponent extends EasyFormControl {\r\n\r\n}\r\n","@if (hasInitialized()) {\r\n @if (easyFormControl().schema?.label) {\r\n <label class=\"ef-form-label\" [for]=\"easyFormControl().id\">{{ easyFormControl().schema?.label | observe }}</label>\r\n }\r\n @if (easyFormControl().schema?.options) {\r\n <div class=\"ef-radio-container\">\r\n @for (option of (easyFormControl().schema?.options | observe); track option.value) {\r\n <label class=\"ef-radio-option\">\r\n <input bindEvents type=\"radio\" [formControl]=\"easyFormControl().control!\" [name]=\"easyFormControl().id!\"\r\n [value]=\"option.value\" [attr.aria-describedby]=\"easyFormControl().id\">\r\n <span class=\"ef-form-label\">{{ option.label | observe }}</span>\r\n </label>\r\n }\r\n </div>\r\n }\r\n <ef-errors [control]=\"easyFormControl().control!\" [formField]=\"easyFormControl().schema!\"/>\r\n}\r\n","import {Component} from '@angular/core';\r\nimport {FormsModule, ReactiveFormsModule} from \"@angular/forms\";\r\nimport { EasyFormControl } from '../../easy-form-control';\r\nimport { EfErrorsComponent } from '../../components/ef-errors/ef-errors.component';\r\nimport { ObservePipe } from '../../pipes/observe';\r\nimport {BindEventsDirective} from \"../../directives/bind-events.directive\";\r\n\r\n@Component({\r\n selector: 'lib-ef-switch',\r\n standalone: true,\r\n imports: [\r\n EfErrorsComponent,\r\n FormsModule,\r\n ObservePipe,\r\n ReactiveFormsModule,\r\n BindEventsDirective\r\n ],\r\n templateUrl: './ef-switch.component.html',\r\n styleUrl: './ef-switch.component.scss'\r\n})\r\nexport class EfSwitchComponent extends EasyFormControl {\r\n\r\n}\r\n","@if (hasInitialized()) {\r\n <input type=\"checkbox\" bindEvents [formControl]=\"easyFormControl().control!\" [id]=\"easyFormControl().id\">\r\n @if (easyFormControl().schema?.label) {\r\n <label class=\"ef-form-label\" [for]=\"easyFormControl().id\">{{ easyFormControl().schema?.label | observe }}</label>\r\n }\r\n <ef-errors [control]=\"easyFormControl().control!\" [formField]=\"easyFormControl().schema!\"/>\r\n}\r\n","import {Component} from '@angular/core';\r\nimport {EasyFormControl} from \"../../easy-form-control\";\r\nimport {ReactiveFormsModule} from \"@angular/forms\";\r\nimport {ObservePipe} from \"../../pipes/observe\";\r\nimport {BindEventsDirective} from \"../../directives/bind-events.directive\";\r\nimport {EfErrorsComponent} from \"../../components/ef-errors/ef-errors.component\";\r\n\r\n@Component({\r\n selector: 'ef-text',\r\n standalone: true,\r\n imports: [\r\n ReactiveFormsModule,\r\n ObservePipe,\r\n EfErrorsComponent,\r\n BindEventsDirective\r\n ],\r\n templateUrl: './ef-text.component.html',\r\n styleUrl: './ef-text.component.scss'\r\n})\r\nexport class EfTextComponent extends EasyFormControl {\r\n}\r\n","@if (hasInitialized()) {\r\n @if (schema()?.label) {\r\n <label class=\"ef-form-label\" [for]=\"easyFormControl().id\">{{ schema()?.label | observe }}</label>\r\n }\r\n <input bindEvents [id]=\"easyFormControl().id\"\r\n [type]=\"props()['type'] ?? 'text'\"\r\n [formControl]=\"control()!\"\r\n [placeholder]=\"props()['placeholder'] ?? ''\"\r\n class=\"ef-input-text\">\r\n <ef-errors [control]=\"control()!\" [formField]=\"schema()!\"/>\r\n}\r\n","import {AfterContentInit, Component, ElementRef, EventEmitter, inject, Input, Output} from '@angular/core';\r\nimport {EASY_FORM_CONFIG, EasyFormConfig} from \"../tokens/easy-form-config\";\r\nimport {EasyForm} from \"../easy-form\";\r\nimport {FormGroup, ReactiveFormsModule} from \"@angular/forms\";\r\nimport {EfTextAreaComponent} from \"../controls/ef-textarea/ef-textarea.component\";\r\nimport {EfSelectComponent} from \"../controls/ef-select/ef-select.component\";\r\nimport {EfCheckboxComponent} from \"../controls/ef-checkbox/ef-checkbox.component\";\r\nimport {EfRadioComponent} from \"../controls/ef-radio/ef-radio.component\";\r\nimport {EfSwitchComponent} from \"../controls/ef-switch/ef-switch.component\";\r\nimport {EfTextComponent} from \"../controls/ef-text/ef-text.component\";\r\n\r\n/**\r\n * EasyFormComponent is the main component that is used to create forms\r\n *\r\n * @see `EasyForm`\r\n */\r\n@Component({\r\n selector: 'easy-form',\r\n standalone: true,\r\n imports: [\r\n ReactiveFormsModule\r\n ],\r\n templateUrl: './easy-form.component.html',\r\n styleUrl: './easy-form.component.scss',\r\n host: {\r\n '[class]': `'show-errors-' + form.options.showErrors`\r\n }\r\n})\r\nexport class EasyFormComponent implements AfterContentInit {\r\n elementRef = inject<ElementRef<HTMLDivElement>>(ElementRef);\r\n _formConfig = inject(EASY_FORM_CONFIG, {optional: true});\r\n\r\n formConfig: EasyFormConfig = this.defaultConfig();\r\n\r\n /**\r\n * EasyForm instance\r\n *\r\n * @type `EasyForm`\r\n */\r\n @Input({required: true}) form!: EasyForm;\r\n @Input() focusFirstError = true;\r\n\r\n /**\r\n * Submit event output\r\n */\r\n @Output() efSubmit = new EventEmitter<FormGroup>();\r\n\r\n constructor() {\r\n if (this._formConfig) {\r\n Object.assign(this.formConfig.controls, this._formConfig.controls);\r\n }\r\n }\r\n\r\n ngAfterContentInit(): void {\r\n\r\n }\r\n\r\n getComponentType(type: string) {\r\n return this.formConfig.controls[type];\r\n }\r\n\r\n handleSubmit($event: any) {\r\n if (this.form.invalid && this.focusFirstError && this.elementRef) {\r\n const firstError = this.elementRef.nativeElement.querySelector('.ng-invalid:not(form), ef-errors:has(*)');\r\n if (firstError) {\r\n setTimeout(() => {\r\n if (firstError.tagName == 'EF-ERRORS') {\r\n firstError.scrollIntoView({behavior: 'smooth', block: 'center'})\r\n } else {\r\n (firstError as HTMLElement).focus()\r\n }\r\n }, 100)\r\n }\r\n }\r\n this.efSubmit.emit(this.form.formGroup)\r\n }\r\n\r\n private defaultConfig() {\r\n return {\r\n controls: {\r\n text: EfTextComponent,\r\n textarea: EfTextAreaComponent,\r\n select: EfSelectComponent,\r\n checkbox: EfCheckboxComponent,\r\n radio: EfRadioComponent,\r\n switch: EfSwitchComponent\r\n }\r\n }\r\n }\r\n}\r\n","@if (form) {\r\n <form [formGroup]=\"form.formGroup\" (ngSubmit)=\"handleSubmit($event)\">\r\n <ng-content/>\r\n </form>\r\n}\r\n","import {Directive, inject, TemplateRef} from '@angular/core';\r\n\r\n@Directive({\r\n selector: 'ng-template[arrayItem]',\r\n standalone: true,\r\n exportAs: 'arrayItem'\r\n})\r\nexport class ArrayItemTemplateDirective {\r\n public templateRef = inject(TemplateRef);\r\n\r\n static ngTemplateContextGuard<T>(dir: ArrayItemTemplateDirective, ctx: any): ctx is {\r\n $implicit: any,\r\n index: number\r\n } {\r\n return true;\r\n }\r\n\r\n}\r\n","import {Directive, inject, TemplateRef} from '@angular/core';\r\n\r\n@Directive({\r\n selector: 'ng-template[arrayWrapper]',\r\n standalone: true,\r\n exportAs: 'arrayWrapper'\r\n})\r\nexport class ArrayWrapperTemplateDirective {\r\n public templateRef = inject(TemplateRef);\r\n\r\n static ngTemplateContextGuard<T>(dir: ArrayWrapperTemplateDirective, ctx: any): ctx is {\r\n $implicit: any,\r\n itemTemplate: TemplateRef<any>\r\n } {\r\n return true;\r\n }\r\n\r\n}\r\n","import {Component, ContentChild, inject, Input, TemplateRef} from '@angular/core';\r\nimport {EasyFormComponent} from \"../../easy-form/easy-form.component\";\r\nimport {NgTemplateOutlet} from \"@angular/common\";\r\nimport {FormArray} from \"@angular/forms\";\r\nim