@koalarx/ui
Version:
Koala UI is a Design System developed in Angular whose objective is to facilitate and make your development faster and simpler, making this framework your greatest ally.
1 lines • 169 kB
Source Map (JSON)
{"version":3,"file":"koalarx-ui-form.mjs","sources":["../../../projects/form/src/lib/btn-submit/btn-submit.component.ts","../../../projects/form/src/lib/btn-submit/btn-submit.component.html","../../../projects/form/src/lib/dynamic-form/enums/dynamic-form-type-field.enum.ts","../../../projects/form/src/lib/dynamic-form/builder/fields/field.base.ts","../../../projects/form/src/lib/dynamic-form/builder/fields/autocomplete.builder.ts","../../../projects/form/src/lib/dynamic-form/builder/fields/field.builder.ts","../../../projects/form/src/lib/dynamic-form/builder/fields/more-items.builder.ts","../../../projects/form/src/lib/dynamic-form/builder/dynamic-form.builder.ts","../../../projects/form/src/lib/dynamic-form/validators/date-min.validator.ts","../../../projects/form/src/lib/dynamic-form/validators/date-max.validator.ts","../../../projects/form/src/lib/dynamic-form/koala.dynamic-form.service.ts","../../../projects/form/src/lib/dynamic-form/validators/validation.helper.ts","../../../projects/form/src/lib/dynamic-form/validators/cpf.validator.ts","../../../projects/form/src/lib/dynamic-form/validators/cnpj.validator.ts","../../../projects/form/src/lib/dynamic-form/validators/autocomplete-selected.validator.ts","../../../projects/form/src/lib/dynamic-form/validators/koala-dynamic-form-validator-result.helper.ts","../../../projects/form/src/lib/show-invalid-fields/show-invalid-fields.ts","../../../projects/form/src/lib/form.abstract.ts","../../../projects/form/src/lib/directives/koala-autofocus.directive.ts","../../../projects/form/src/lib/dynamic-form/dynamic-form.component.ts","../../../projects/form/src/lib/dynamic-form/dynamic-form.component.html","../../../projects/form/src/lib/koala.form.module.ts","../../../projects/form/src/koalarx-ui-form.ts"],"sourcesContent":["import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';\nimport { UntypedFormGroup } from '@angular/forms';\nimport { ThemePalette } from '@angular/material/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { KoalaLanguageHelper } from \"@koalarx/ui/core\";\n\n@Component({\n selector: 'koala-submit',\n templateUrl: 'btn-submit.component.html',\n styleUrls: ['btn-submit.component.css']\n})\nexport class BtnSubmitComponent implements OnInit, OnChanges {\n @Input() fg: UntypedFormGroup;\n @Input() color: ThemePalette = 'primary';\n @Input() btnLabel: string = KoalaLanguageHelper.getBtnLabel();\n @Input() btnSubmitDisabled = false;\n @Input() loader: BehaviorSubject<boolean>;\n @Input() iconButton: boolean;\n @Input() icon: string;\n @Input() iconColor: 'blue' | 'red' | 'yellow' | 'black' | 'green';\n public disabled = new BehaviorSubject<boolean>(false);\n\n ngOnInit() {\n if (!this.btnLabel) {\n this.btnLabel = KoalaLanguageHelper.getBtnLabel();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n if (changes.btnSubmitDisabled) {\n this.disabled.next(changes.btnSubmitDisabled.currentValue);\n }\n }\n}\n","<button\n\t*ngIf=\"!iconButton else btnIcon\"\n\t[color]=\"color\"\n\t[disabled]=\"(disabled | async) || fg.invalid || fg.pending\"\n\tmat-raised-button\n\ttype=\"submit\">\n <span>{{btnLabel}}</span>\n <mat-spinner *ngIf=\"loader | async\" diameter=\"20\"></mat-spinner>\n</button>\n<ng-template #btnIcon>\n <button\n\t [color]=\"color\"\n\t [disabled]=\"(disabled | async) || fg.invalid || fg.pending\"\n\t class=\"koala-icon-button\"\n\t mat-icon-button\n\t type=\"submit\">\n <mat-spinner *ngIf=\"loader | async\" [color]=\"color\" diameter=\"20\"></mat-spinner>\n <mat-icon *ngIf=\"!(loader | async)\">{{icon}}</mat-icon>\n </button>\n</ng-template>\n","export enum DynamicFormTypeFieldEnum {\n text = 1,\n password,\n cpf,\n cnpj,\n datetime,\n email,\n phone,\n number,\n valueList,\n textarea,\n time,\n hoursAndMinutes,\n checkbox,\n select,\n coin,\n percent,\n moreItems,\n id,\n textLogs,\n file,\n autocomplete,\n color,\n dynamicForm,\n date,\n radio,\n float,\n stringNumber,\n selectMultipleNative,\n month,\n competenceDate,\n stringWithCustomMasc\n}\n","import { KoalaDynamicFormFieldInterface } from \"../../interfaces/koala.dynamic-form-field.interface\";\nimport { DynamicFormTypeFieldEnum } from \"../../enums/dynamic-form-type-field.enum\";\nimport { FloatLabelType, MatFormFieldAppearance } from \"@angular/material/form-field\";\nimport { AsyncValidatorFn, UntypedFormBuilder, ValidatorFn } from \"@angular/forms\";\nimport { KoalaDynamicFormConfigInterface } from \"../../interfaces/koala.dynamic-form-config.interface\";\nimport { koala } from \"@koalarx/utils\";\nimport { DeviceDetectorService } from \"ngx-device-detector\";\nimport { DynamicFormBuilder } from \"../dynamic-form.builder\";\n\nexport abstract class FieldBase {\n protected readonly fieldConfig: KoalaDynamicFormFieldInterface;\n\n protected constructor(\n label: string,\n name: string,\n type: DynamicFormTypeFieldEnum,\n private formConfig: KoalaDynamicFormConfigInterface,\n protected fb: UntypedFormBuilder,\n protected deviceService: DeviceDetectorService\n ) {\n this.fieldConfig = {\n label,\n name,\n type\n }\n this.appearance().grid();\n }\n\n public hide(hide: boolean = true) {\n this.fieldConfig.show = !hide;\n return this;\n }\n\n public focus() {\n this.fieldConfig.focus = true;\n return this;\n }\n\n public syncValidator(validators: ValidatorFn[]) {\n this.fieldConfig.syncValidators = validators;\n return this;\n }\n\n public asyncValidator(validators: AsyncValidatorFn | AsyncValidatorFn[]) {\n this.fieldConfig.asyncValidators = validators;\n return this;\n }\n\n public disabled(disabled: boolean = true) {\n this.fieldConfig.disabled = disabled;\n return this;\n }\n\n public required(required: boolean = true) {\n this.fieldConfig.required = required;\n return this;\n }\n\n public textHint(hint: string) {\n this.fieldConfig.textHint = hint;\n return this;\n }\n\n public min(min: number) {\n this.fieldConfig.min = min;\n return this;\n }\n\n public max(max: number) {\n this.fieldConfig.max = max;\n return this;\n }\n\n public minLength(min: number) {\n this.fieldConfig.minLength = min;\n return this;\n }\n\n public maxLength(max: number) {\n this.fieldConfig.maxLength = max;\n return this;\n }\n\n public multiple(multiple = true) {\n this.fieldConfig.multiple = multiple;\n return this;\n }\n\n public valueChanges<T>(fn: (value: T) => void) {\n this.fieldConfig.valueChanges = fn;\n return this;\n }\n\n public setValue(value: any) {\n this.fieldConfig.value = value;\n return this;\n }\n\n public appearance(type: MatFormFieldAppearance = \"outline\", floatLabel: FloatLabelType = \"always\") {\n this.fieldConfig.appearance = type;\n this.fieldConfig.floatLabel = floatLabel;\n return this;\n }\n\n public grid(size: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 = 12, width: number = 100) {\n if (this.deviceService.isMobile()) {\n size = 12;\n }\n\n for (let colSize = 12; colSize >= 1; colSize--) {\n this.fieldConfig.class = this.fieldConfig.class?.replace('col-' + colSize, '');\n }\n this.addClass('col-' + size);\n this.addFieldClass('w-' + width);\n\n return this;\n }\n\n public setOptions(options: { value: any; name: string; }[]) {\n this.fieldConfig.opcoesSelect = options;\n return this;\n }\n\n public addClass(className: string) {\n if (\n this.deviceService.isMobile() &&\n className.indexOf('col-') >= 0 &&\n className.indexOf('col-12') === 0\n ) {\n className = className.replace('col-1', 'col-12')\n .replace('col-2', 'col-12')\n .replace('col-3', 'col-12')\n .replace('col-4', 'col-12')\n .replace('col-5', 'col-12')\n .replace('col-6', 'col-12')\n .replace('col-7', 'col-12')\n .replace('col-8', 'col-12')\n .replace('col-9', 'col-12')\n .replace('col-10', 'col-12')\n .replace('col-11', 'col-12');\n }\n\n this.fieldConfig.class = koala(`${this.fieldConfig?.class ?? ''} ${className}`)\n .string()\n .split(' ')\n .clearEmptyValues()\n .toString(' ')\n .getValue();\n return this;\n }\n\n public addFieldClass(className: string) {\n this.fieldConfig.fieldClass = koala(`${this.fieldConfig?.fieldClass ?? ''} ${className}`)\n .string()\n .split(' ')\n .clearEmptyValues()\n .toString(' ')\n .getValue();\n return this;\n }\n\n public setCustomMasc(mask: string, config?: {\n thousandSeparator?: string;\n suffix?: string;\n prefix?: string;\n }) {\n this.fieldConfig.customMasc = mask;\n this.fieldConfig.customMascThousandSeparator = config?.thousandSeparator;\n this.fieldConfig.customMascSuffix = config?.suffix;\n this.fieldConfig.customMascPrefix = config?.prefix;\n return this;\n }\n\n public generate() {\n let getLastConfig = (this.formConfig.formConfig.length > 0) ?\n this.formConfig.formConfig[this.formConfig.formConfig.length - 1] :\n null;\n\n if (getLastConfig?.type === DynamicFormTypeFieldEnum.moreItems && getLastConfig?.name !== 'endMoreItems') {\n this.formConfig.formConfig[this.formConfig.formConfig.length - 1].moreItemsConfig.formConfig.push(this.fieldConfig);\n } else {\n if (getLastConfig?.name === 'endMoreItems') {\n this.formConfig.formConfig.splice(this.formConfig.formConfig.length - 1, 1);\n }\n\n this.formConfig.formConfig.push(this.fieldConfig);\n }\n return new DynamicFormBuilder(\n this.fb,\n this.deviceService,\n this.formConfig.formConfig\n );\n }\n}\n","import { KoalaDynamicFormConfigInterface } from \"../../interfaces/koala.dynamic-form-config.interface\";\nimport { DynamicFormTypeFieldEnum } from \"../../enums/dynamic-form-type-field.enum\";\nimport { BehaviorSubject, Observable } from \"rxjs\";\nimport { KoalaDynamicAutocompleteOptionsInterface } from \"../../interfaces/koala.dynamic-autocomplete-options.interface\";\nimport { UntypedFormBuilder } from \"@angular/forms\";\nimport { KoalaDynamicFormAutocompleteMultipleConfigInterface } from \"../../interfaces/koala.dynamic-form-autocomplete-multiple-config.interface\";\nimport { FieldBase } from \"./field.base\";\nimport { DeviceDetectorService } from \"ngx-device-detector\";\n\nexport class AutocompleteBuilder extends FieldBase {\n private service$: Observable<KoalaDynamicAutocompleteOptionsInterface[]>;\n\n constructor(\n label: string,\n name: string,\n formConfig: KoalaDynamicFormConfigInterface,\n fb: UntypedFormBuilder,\n deviceService: DeviceDetectorService\n ) {\n super(label, name, DynamicFormTypeFieldEnum.autocomplete, formConfig, fb, deviceService);\n }\n\n public service(service: Observable<KoalaDynamicAutocompleteOptionsInterface[]>) {\n this.service$ = service;\n return this;\n }\n\n public defaultValueOnClean(value: any) {\n this.fieldConfig.autocompleteDefaultValueOnClear = value;\n return this;\n }\n\n public loadOptions(type: 'all' | 'onDemand', onDemandFilter?: (filter: string) => Observable<KoalaDynamicAutocompleteOptionsInterface[]>) {\n this.fieldConfig.autocompleteType = type;\n\n if (type === \"all\") {\n const options$ = new BehaviorSubject<KoalaDynamicAutocompleteOptionsInterface[]>([]);\n this.service$.subscribe(options => options$.next(options));\n this.fieldConfig.autocompleteOptions = options$;\n } else {\n this.fieldConfig.autocompleteFilter = onDemandFilter;\n }\n\n return this;\n }\n\n public colorChipConfig(fn: (subject: BehaviorSubject<KoalaDynamicFormAutocompleteMultipleConfigInterface>) => void) {\n this.fieldConfig.autocompleteMultipleConfig = new BehaviorSubject<KoalaDynamicFormAutocompleteMultipleConfigInterface>(null);\n fn(this.fieldConfig.autocompleteMultipleConfig);\n return this;\n }\n\n public addOption(active: boolean = true) {\n this.fieldConfig.autocompleteAddOption = active;\n return this;\n }\n}\n","import { DynamicFormTypeFieldEnum } from \"../../enums/dynamic-form-type-field.enum\";\nimport { FieldBase } from \"./field.base\";\nimport { UntypedFormBuilder } from \"@angular/forms\";\nimport { KoalaDynamicFormConfigInterface } from \"../../interfaces/koala.dynamic-form-config.interface\";\nimport { DeviceDetectorService } from \"ngx-device-detector\";\n\nexport class FieldBuilder extends FieldBase {\n\n constructor(\n label: string,\n name: string,\n type: DynamicFormTypeFieldEnum,\n formConfig: KoalaDynamicFormConfigInterface,\n fb: UntypedFormBuilder,\n deviceService: DeviceDetectorService\n ) {\n super(label, name, type, formConfig, fb, deviceService);\n }\n}\n","import { DynamicFormTypeFieldEnum } from \"../../enums/dynamic-form-type-field.enum\";\nimport { UntypedFormBuilder } from \"@angular/forms\";\nimport { BehaviorSubject } from \"rxjs\";\nimport { KoalaDynamicSetValueInterface } from \"../../interfaces/koala.dynamic-set-value.interface\";\nimport { KoalaDynamicFormFieldInterface } from \"../../interfaces/koala.dynamic-form-field.interface\";\nimport { KoalaDynamicFormConfigInterface } from \"../../interfaces/koala.dynamic-form-config.interface\";\nimport { DeviceDetectorService } from \"ngx-device-detector\";\nimport { DynamicFormBuilder } from \"../dynamic-form.builder\";\n\nexport class MoreItemsBuilder {\n private fieldConfig: KoalaDynamicFormFieldInterface;\n\n constructor(\n private label: string,\n private name: string,\n private btnAddLabel: string,\n private min: number,\n private max: number,\n private formConfig: KoalaDynamicFormConfigInterface,\n private fb: UntypedFormBuilder,\n private deviceService: DeviceDetectorService,\n ) {\n }\n\n public build() {\n let getLastConfig = (this.formConfig.formConfig.length > 0) ?\n this.formConfig.formConfig[this.formConfig.formConfig.length - 1] :\n null;\n\n this.fieldConfig = {\n label: this.label,\n name: this.name,\n type: DynamicFormTypeFieldEnum.moreItems,\n moreItemsIconBackgroundColor: '#fff',\n moreItemsIconFontColor: '#212121',\n moreItemsMinItems: this.min,\n moreItemsMaxItems: this.max,\n moreItemsButtonIconAddlabel: this.btnAddLabel,\n moreItemsConfig: {\n form: this.fb.group({}),\n formConfig: [],\n setValues: new BehaviorSubject<BehaviorSubject<KoalaDynamicSetValueInterface[]>[]>([])\n }\n };\n\n if (getLastConfig?.type === DynamicFormTypeFieldEnum.moreItems && getLastConfig?.name !== 'endMoreItems') {\n let formConfigMoreItems = getLastConfig.moreItemsConfig.formConfig as KoalaDynamicFormFieldInterface[];\n if (formConfigMoreItems.length > 0) {\n let lastIndexMoreItems = 0;\n formConfigMoreItems.forEach((item, index) => {\n if (item.type === DynamicFormTypeFieldEnum.moreItems) lastIndexMoreItems = index;\n });\n formConfigMoreItems[lastIndexMoreItems].moreItemsConfig.formConfig.push(this.fieldConfig);\n } else {\n this.formConfig.formConfig[this.formConfig.formConfig.length - 1].moreItemsConfig.formConfig.push(this.fieldConfig);\n }\n } else {\n if (getLastConfig?.name === 'endMoreItems') {\n this.formConfig.formConfig.splice(this.formConfig.formConfig.length - 1, 1);\n }\n this.formConfig.formConfig.push(this.fieldConfig);\n }\n\n return new DynamicFormBuilder(\n this.fb,\n this.deviceService,\n this.formConfig.formConfig\n );\n }\n}\n","import { UntypedFormBuilder } from \"@angular/forms\";\nimport { KoalaDynamicFormConfigInterface } from \"../interfaces/koala.dynamic-form-config.interface\";\nimport { KoalaDynamicFormFieldInterface } from \"../interfaces/koala.dynamic-form-field.interface\";\nimport { DynamicFormTypeFieldEnum } from \"../enums/dynamic-form-type-field.enum\";\nimport { AutocompleteBuilder } from \"./fields/autocomplete.builder\";\nimport { BehaviorSubject } from \"rxjs\";\nimport { KoalaDynamicSetValueInterface } from \"../interfaces/koala.dynamic-set-value.interface\";\nimport { KoalaDynamicFormShowFieldInterface } from \"../interfaces/koala.dynamic-form-show-field.interface\";\nimport { koala } from \"@koalarx/utils\";\nimport { DeviceDetectorService } from \"ngx-device-detector\";\nimport { FieldBuilder } from \"./fields/field.builder\";\nimport { MoreItemsBuilder } from \"./fields/more-items.builder\";\n\nexport type DynamicFormFieldType = 'text' | 'password' | 'cpf' | 'cnpj' | 'datetime' | 'email' | 'phone' | 'number' | 'stringNumber' | 'valueList' | 'textarea' | 'time' | 'hoursAndMinutes' | 'checkbox' | 'select' | 'selectMultipleNative' | 'coin' | 'percent' | 'id' | 'textLogs' | 'color' | 'date' | 'radio' | 'float' | 'month' | 'competenceDate' | 'stringWithCustomMasc';\n\nexport class DynamicFormBuilder {\n private readonly config: KoalaDynamicFormConfigInterface;\n\n constructor(\n private fb: UntypedFormBuilder,\n private deviceService: DeviceDetectorService,\n configInMemory?: KoalaDynamicFormFieldInterface[]) {\n this.config = {\n form: fb.group({}),\n formConfig: configInMemory ?? [],\n setValues: new BehaviorSubject<KoalaDynamicSetValueInterface[]>(null),\n showFields: new BehaviorSubject<KoalaDynamicFormShowFieldInterface[]>(null)\n }\n }\n\n public field(label: string, name: string, type: DynamicFormFieldType) {\n switch (type) {\n case \"id\":\n case \"text\":\n case \"textarea\":\n case \"number\":\n case \"stringNumber\":\n case \"cnpj\":\n case \"cpf\":\n case \"coin\":\n case \"color\":\n case \"date\":\n case \"datetime\":\n case \"email\":\n case \"float\":\n case \"password\":\n case \"percent\":\n case \"phone\":\n case \"time\":\n case \"hoursAndMinutes\":\n case \"textLogs\":\n case \"valueList\":\n case \"checkbox\":\n case \"radio\":\n case \"select\":\n case \"selectMultipleNative\":\n case \"month\":\n case \"competenceDate\":\n case \"stringWithCustomMasc\":\n return new FieldBuilder(label, name, DynamicFormTypeFieldEnum[type], this.config, this.fb, this.deviceService);\n }\n }\n\n public autocomplete(label: string, name: string) {\n return new AutocompleteBuilder(label, name, this.config, this.fb, this.deviceService);\n }\n\n public simpleMoreItems(label: string, name: string, btnAddLabel: string, min: number, max: number) {\n return new MoreItemsBuilder(\n label,\n name,\n btnAddLabel,\n min,\n max,\n this.config,\n this.fb,\n this.deviceService\n );\n }\n\n public autofill(object: any) {\n if (object) {\n const setValues: KoalaDynamicSetValueInterface[] = [];\n Object.keys(object).forEach(indexName => {\n\n const arrField = koala(this.config.formConfig).array<KoalaDynamicFormFieldInterface>().filter(indexName, 'name', {comparator: \"=\"}).getValue();\n if (arrField.length === 1) {\n\n const field = arrField[0] ?? null;\n\n if (\n typeof object[indexName] !== \"object\" ||\n field.type === DynamicFormTypeFieldEnum.autocomplete ||\n field.type === DynamicFormTypeFieldEnum.selectMultipleNative\n ) {\n if (field.type === DynamicFormTypeFieldEnum.textLogs) {\n field.textObs = object[indexName];\n } else {\n setValues.push({\n name: indexName,\n value: object[indexName]\n });\n }\n } else {\n if (field.type === DynamicFormTypeFieldEnum.moreItems) {\n const setValuesMoreItems = [];\n const objectMoreItems = object[indexName] as any[];\n objectMoreItems.forEach(objectItem => {\n const moreItemValues: KoalaDynamicSetValueInterface[] = [];\n Object.keys(objectItem).forEach(objectIndexName => {\n moreItemValues.push({\n name: objectIndexName,\n value: objectItem[objectIndexName]\n });\n });\n setValuesMoreItems.push(new BehaviorSubject<KoalaDynamicSetValueInterface[]>(moreItemValues));\n });\n\n field.moreItemsConfig?.setValues?.next(setValuesMoreItems);\n } else if (field.type === DynamicFormTypeFieldEnum.dynamicForm) {\n const dynamicFormObject = object[indexName];\n const dynamicFormSetValues: KoalaDynamicSetValueInterface[] = [];\n\n Object.keys(dynamicFormObject).forEach(dynamicFormIndexName => {\n const arrDynamicField = koala(field.dynamicFormConfig.formConfig).array<KoalaDynamicFormFieldInterface>().filter(indexName, 'name').getValue();\n const dynamicField = arrDynamicField[0] ?? null;\n\n if (dynamicField?.type === DynamicFormTypeFieldEnum.textLogs) {\n dynamicField.textObs = object[indexName];\n } else {\n dynamicFormSetValues.push({\n name: dynamicFormIndexName,\n value: dynamicFormObject[dynamicFormIndexName]\n });\n }\n });\n\n field.dynamicFormConfig?.setValues?.next(dynamicFormSetValues);\n } else {\n this.autofill(object[indexName]);\n }\n }\n }\n });\n this.config?.setValues?.next(setValues);\n }\n\n return this;\n }\n\n public literalConfig(config: KoalaDynamicFormFieldInterface) {\n this.config.formConfig.push(config);\n if (config.type === DynamicFormTypeFieldEnum.moreItems) this.generateMoreItems();\n return this;\n }\n\n public generate(tabIndexStart = 0) {\n this.config.formConfig = this.config.formConfig.filter(config => config.name !== 'endMoreItems');\n this.config.tabIndexStart = tabIndexStart;\n return this.config;\n }\n\n public generateMoreItems() {\n this.config.formConfig.push({\n name: 'endMoreItems',\n type: DynamicFormTypeFieldEnum.moreItems\n });\n return new DynamicFormBuilder(\n this.fb,\n this.deviceService,\n this.config.formConfig\n );\n }\n}\n","import { AbstractControl, ValidationErrors } from \"@angular/forms\";\nimport { KoalaCustomValidatorFnInterface } from \"../interfaces/koala-custom-validator-fn.interface\";\n\nexport function DateMinValidator(min: string): KoalaCustomValidatorFnInterface {\n return (control: AbstractControl): ValidationErrors | null => {\n if (control.value && typeof min === 'string') {\n if (new Date(control.value) < new Date(min)) {\n return {dateMin: true};\n }\n }\n return null;\n }\n}\n","import { AbstractControl, ValidationErrors } from \"@angular/forms\";\nimport { KoalaCustomValidatorFnInterface } from \"../interfaces/koala-custom-validator-fn.interface\";\n\nexport function DateMaxValidator(max: string): KoalaCustomValidatorFnInterface {\n return (control: AbstractControl): ValidationErrors | null => {\n if (control.value && typeof max === 'string') {\n if (new Date(control.value) > new Date(max)) {\n return {dateMax: true};\n }\n }\n return null;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { DynamicFormTypeFieldEnum } from './enums/dynamic-form-type-field.enum';\nimport { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';\nimport { KoalaDynamicSetValueInterface } from './interfaces/koala.dynamic-set-value.interface';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport { KoalaDynamicAutocompleteOptionsInterface } from './interfaces/koala.dynamic-autocomplete-options.interface';\nimport { KoalaDynamicFormShowFieldInterface } from './interfaces/koala.dynamic-form-show-field.interface';\nimport { KoalaDynamicFormConfigInterface } from './interfaces/koala.dynamic-form-config.interface';\nimport { DynamicFormBuilder } from \"./builder/dynamic-form.builder\";\nimport { koala } from \"@koalarx/utils\";\nimport { DateMinValidator } from \"./validators/date-min.validator\";\nimport { DateMaxValidator } from \"./validators/date-max.validator\";\nimport { DeviceDetectorService } from \"ngx-device-detector\";\nimport { unmaskCoin } from \"@koalarx/utils/operators/string\";\n\nexport type KoalaDynamicFormValidatorType = 'required' | 'min' | 'max';\n\n@Injectable({providedIn: \"any\"})\nexport class KoalaDynamicFormService {\n\n constructor(\n protected fb: UntypedFormBuilder,\n protected deviceService: DeviceDetectorService) {\n }\n\n public build() {\n return new DynamicFormBuilder(this.fb, this.deviceService);\n }\n\n public updateValidator(formGroup: UntypedFormGroup, name: string, type: KoalaDynamicFormValidatorType, value: boolean | number | string) {\n if (type === 'required' && typeof value !== 'boolean') {\n throw new Error(`Type required cannot be a ${typeof value}`);\n } else if ((type === 'min' || type === 'max') && typeof value === \"boolean\") {\n throw new Error(`Type ${type} cannot be a boolean`);\n }\n\n const formArray = formGroup.get('formData') as UntypedFormArray;\n const control = formArray.controls.find(control => control.get('name').value === name);\n\n if (control) {\n const currentMin = control.get('min').value;\n const currentMax = control.get('max').value;\n const validators = [];\n\n control.get('value').clearValidators();\n control.get('value').setErrors(null);\n\n if (type === \"required\" && value) {\n validators.push(Validators.required);\n control.get('value').setErrors({required: true});\n }\n if ((type === \"min\" || currentMin)) {\n if (typeof value === \"number\") {\n validators.push(Validators.min((type === \"min\" ? value : currentMin)));\n control.get('value').setErrors({min: true});\n }\n else if (typeof value === \"string\") {\n validators.push(DateMinValidator((type === \"min\" ? value : currentMin)));\n control.get('value').setErrors({dateMin: true});\n }\n }\n if ((type === \"max\" || currentMax)) {\n if (typeof value === \"number\") {\n validators.push(Validators.max((type === \"max\" ? value : currentMax)));\n control.get('value').setErrors({max: true});\n }\n else if (typeof value === \"string\") {\n validators.push(DateMaxValidator((type === \"max\" ? value : currentMax)));\n control.get('value').setErrors({dateMax: true});\n }\n }\n\n if (type === \"required\") {\n control.get('required').setValue(value);\n } else if (type === \"min\") {\n control.get('min').setValue(value);\n } else if (type === \"max\") {\n control.get('max').setValue(value);\n }\n control.get('value').setValidators(validators);\n control.get('value').updateValueAndValidity();\n }\n }\n\n public disableFields(formGroup: UntypedFormGroup, disabled: boolean, fields: string[]) {\n const formArray = formGroup.get('formData') as UntypedFormArray;\n\n fields.forEach(field => {\n const controlValue = formArray.controls.find(control => field === control.get('name').value)?.get('value');\n\n if (controlValue && disabled) {\n controlValue.disable();\n } else if (controlValue && !disabled) {\n controlValue.enable();\n }\n\n const controlDisabled = formArray.controls.find(control => field === control.get('name').value)?.get('disabled');\n controlDisabled.setValue(disabled);\n });\n }\n\n public emitData(form: UntypedFormGroup) {\n const data = {};\n const formArray = form.get('formData') as UntypedFormArray;\n formArray?.controls.forEach(control => {\n if (control.get('show').value.getValue() !== false) {\n let value: any = control.get('value').value;\n if (control.get('type').value === DynamicFormTypeFieldEnum.valueList) {\n if (value === null || value === undefined) {\n value = '';\n }\n value = koala(value).string().split().getValue();\n } else if (control.get('type').value === DynamicFormTypeFieldEnum.moreItems) {\n const moreItems = control.get('moreItemsConfig').value as { form: UntypedFormGroup }[];\n value = [];\n moreItems.forEach(item => {\n value.push(this.emitData(item.form));\n });\n } else if (control.get('type').value === DynamicFormTypeFieldEnum.autocomplete) {\n if (control.get('multiple').value) {\n const options = control.get('autocompleteSelectedValue').value as KoalaDynamicAutocompleteOptionsInterface[];\n value = options?.map(item => item?.value);\n } else {\n value = (control.get('autocompleteSelectedValue').value?.value ?\n control.get('autocompleteSelectedValue').value.value :\n control.get('autocompleteSelectedValue').value\n );\n }\n } else if (control.get('type').value === DynamicFormTypeFieldEnum.dynamicForm) {\n const dynamicFormConfig = control.get('dynamicFormConfig').value as BehaviorSubject<KoalaDynamicFormConfigInterface>;\n value = this.emitData(dynamicFormConfig.getValue().form);\n } else if (control.get('type').value === DynamicFormTypeFieldEnum.number) {\n value = parseInt(value);\n } else if ((\n control.get('type').value === DynamicFormTypeFieldEnum.float ||\n control.get('type').value === DynamicFormTypeFieldEnum.percent\n ) && typeof value === \"string\") {\n value = parseFloat(value.replace(/,/g, '.'));\n } else if (\n control.get('type').value === DynamicFormTypeFieldEnum.coin &&\n typeof value === \"string\"\n ) {\n value = unmaskCoin(value);\n }\n data[control.get('name').value] = value;\n }\n });\n\n return data;\n }\n\n public resetForm(form: UntypedFormGroup) {\n const formArray = form.get('formData') as UntypedFormArray;\n formArray.controls.forEach(control => {\n if (control.get('type').value === DynamicFormTypeFieldEnum.moreItems) {\n control.get('moreItemsConfig').setValue([]);\n } else {\n control.get('value').reset();\n }\n });\n }\n\n public setValuesInMoreItemsForm(\n subject: BehaviorSubject<BehaviorSubject<KoalaDynamicSetValueInterface[]>[]>,\n values: KoalaDynamicSetValueInterface[][]\n ) {\n const valuesMoreItems = [];\n values.forEach(itemValue => {\n valuesMoreItems.push(new BehaviorSubject<KoalaDynamicSetValueInterface[]>(itemValue));\n });\n subject.next(valuesMoreItems);\n }\n\n public autocompleteFilterOnServer(\n request: () => Promise<any[]>,\n nameConfig: {\n propsByName: string[];\n delimiter: string;\n },\n indexNameByValue?: string\n ) {\n return new Observable<KoalaDynamicAutocompleteOptionsInterface[]>(observe => {\n request().then(response => {\n const options: KoalaDynamicAutocompleteOptionsInterface[] = [];\n response.forEach(item => {\n let value = '';\n if (indexNameByValue?.indexOf(' > ') >= 0) {\n value = this.getValueByStringPath(indexNameByValue, item);\n } else if (indexNameByValue) {\n value = item[indexNameByValue];\n } else {\n value = item;\n }\n options.push({\n name: koala(item).object().toString(\n nameConfig.propsByName,\n (nameConfig.delimiter ?? ' ')\n ).getValue(),\n value\n });\n });\n observe.next(options);\n });\n });\n }\n\n public showFields(\n subject: BehaviorSubject<KoalaDynamicFormShowFieldInterface[]>,\n names: string[],\n show: boolean,\n clearCurrentValue = false\n ) {\n const fields: KoalaDynamicFormShowFieldInterface[] = [];\n names.forEach(name => {\n fields.push({\n name,\n show,\n clearCurrentValue\n });\n });\n subject.next(fields);\n }\n\n private getValueByStringPath(indexNameByValue: string, item: any) {\n let value;\n const partsIndex = indexNameByValue.split(' > ');\n let partIndex = 0;\n do {\n if (!value) {\n value = item[partsIndex[partIndex]];\n } else {\n value = value[partsIndex[partIndex]];\n }\n partIndex++;\n } while (partIndex < partsIndex.length);\n\n return value;\n }\n}\n","export class ValidationHelper {\n public static validateCpf(value: string) {\n function calcChecker1(digits: any) {\n let sum: number | null = null;\n\n for (let j = 0; j < 9; ++j) {\n sum += digits.toString().charAt(j) * (10 - j);\n }\n\n const lastSumChecker1 = sum % 11;\n\n return lastSumChecker1 < 2 ? 0 : 11 - lastSumChecker1;\n }\n\n function calcChecker2(cpfWithChecker1: any) {\n let sum: number | null = null;\n\n for (let k = 0; k < 10; ++k) {\n sum += cpfWithChecker1.toString().charAt(k) * (11 - k);\n }\n\n const lastSumChecker2 = sum % 11;\n\n return lastSumChecker2 < 2 ? 0 : 11 - lastSumChecker2;\n }\n\n const cleanCPF = value.replace(/\\.|\\-|\\s/g, '');\n const firstNineDigits = cleanCPF.substring(0, 9);\n const checker = cleanCPF.substring(9, 11);\n\n if (cleanCPF.length !== 11) {\n return false;\n }\n\n // Checking if all digits are equal\n for (let i = 0; i < 10; i++) {\n if ('' + firstNineDigits + checker === Array(12).join(`${i}`)) {\n return false;\n }\n }\n\n const checker1 = calcChecker1(firstNineDigits);\n const checker2 = calcChecker2(firstNineDigits + '' + checker1);\n\n return checker.toString() === checker1.toString() + checker2.toString();\n }\n\n public static validateCnpj(value: string) {\n value = value.replace(/[^\\d]+/g, '');\n\n if (value === '') {\n return false;\n }\n\n if (value.length !== 14) {\n return false;\n }\n\n // Elimina CNPJs invalidos conhecidos\n if (value === '00000000000000' ||\n value === '11111111111111' ||\n value === '22222222222222' ||\n value === '33333333333333' ||\n value === '44444444444444' ||\n value === '55555555555555' ||\n value === '66666666666666' ||\n value === '77777777777777' ||\n value === '88888888888888' ||\n value === '99999999999999') {\n return false;\n }\n\n // Valida DVs\n let tamanho = value.length - 2;\n let numeros = value.substring(0, tamanho);\n const digitos = value.substring(tamanho);\n let soma = 0;\n let pos = tamanho - 7;\n for (let i = tamanho; i >= 1; i--) {\n soma += parseInt(numeros.charAt(tamanho - i), 10) * pos--;\n if (pos < 2) {\n pos = 9;\n }\n }\n let resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;\n if (resultado !== parseInt(digitos.charAt(0), 10)) {\n return false;\n }\n\n tamanho = tamanho + 1;\n numeros = value.substring(0, tamanho);\n soma = 0;\n pos = tamanho - 7;\n for (let i = tamanho; i >= 1; i--) {\n soma += parseInt(numeros.charAt(tamanho - i), 10) * pos--;\n if (pos < 2) {\n pos = 9;\n }\n }\n resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;\n\n return !(resultado !== parseInt(digitos.charAt(1), 10));\n }\n}\n","import { AbstractControl } from '@angular/forms';\nimport { ValidationHelper } from './validation.helper';\n\nexport function CpfValidator(control: AbstractControl) {\n if (control.value) {\n if (control.value.length <= 14 && !ValidationHelper.validateCpf(control.value)) {\n return {cpfInvalid: true};\n }\n }\n return null;\n}\n","import { AbstractControl } from '@angular/forms';\nimport { ValidationHelper } from './validation.helper';\n\nexport function CnpjValidator(control: AbstractControl) {\n if (control.value) {\n if (control.value.length > 14 && !ValidationHelper.validateCnpj(control.value)) {\n return {cnpjInvalid: true};\n }\n }\n return null;\n}\n","import { AbstractControl } from '@angular/forms';\n\nexport function AutocompleteSelectedValidator(control: AbstractControl) {\n if (\n control.value &&\n control.value.hasOwnProperty('value') &&\n control.value.hasOwnProperty('name') &&\n Object.keys(control.value).length === 2\n ) {\n return null;\n }\n\n return {autocompleteSelected: true};\n}\n","export class KoalaDynamicFormValidatorResultHelper {\n\n public static generate(errorMessage: string) {\n return {\n customError: {\n message: errorMessage\n }\n }\n }\n}\n","import { ErrorStateMatcher } from '@angular/material/core';\nimport { UntypedFormControl, FormGroupDirective, NgForm } from '@angular/forms';\n\nexport class ShowInvalidFields implements ErrorStateMatcher {\n\n constructor() {\n }\n\n isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean {\n const isSubmitted = form && form.submitted;\n return !!(control && control.invalid && (control.errors || control.dirty || control.touched || isSubmitted));\n }\n}\n","import { ShowInvalidFields } from './show-invalid-fields/show-invalid-fields';\nimport { UntypedFormGroup } from '@angular/forms';\nimport { BehaviorSubject } from 'rxjs';\n\nexport abstract class FormAbstract {\n public showInvalidFields: ShowInvalidFields;\n public btnLabel: string;\n public loader = new BehaviorSubject<boolean>(false);\n public btnSubmitDisabled = false;\n public getData = new BehaviorSubject<boolean>(false);\n\n protected constructor(private formAbstract: () => UntypedFormGroup) {\n }\n\n public selecionarAutocomplete(controlName: string, obj: any, indexName?: string) {\n if (obj) {\n let value = indexName ? obj[indexName] : obj;\n if (Array.isArray(obj)) {\n value = [];\n obj.forEach(item => {\n value.push(indexName ? item[indexName] : item);\n });\n }\n\n this.formAbstract().get(controlName).setValue(value);\n } else {\n this.formAbstract().get(controlName).setValue('');\n }\n }\n\n public btnClickGetData() {\n this.getData.next(true);\n }\n\n protected enableShowInvalidFields() {\n this.showInvalidFields = new ShowInvalidFields();\n }\n\n protected loading(show: boolean = true, btnLabel?: string) {\n this.btnSubmitDisabled = show;\n this.loader.next(show);\n\n if (show) {\n this.btnLabel = btnLabel ? btnLabel : 'Enviando Dados...';\n } else {\n this.btnLabel = btnLabel ? btnLabel : 'Enviar';\n }\n }\n}\n","import { AfterContentInit, Directive, ElementRef, Input } from '@angular/core';\n\n@Directive({\n\tselector: '[koalaAutoFocus]'\n})\nexport class KoalaAutofocusDirective implements AfterContentInit {\n\t@Input() public koalaAutoFocus: boolean;\n\t\n\tpublic constructor(private el: ElementRef) {}\n\t\n\tpublic ngAfterContentInit() {\n\t\tif (this.koalaAutoFocus) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.el.nativeElement.focus();\n\t\t\t}, 500);\n\t\t}\n\t}\n}\n","import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators, AbstractControl } from '@angular/forms';\nimport { KoalaDynamicFormFieldInterface } from './interfaces/koala.dynamic-form-field.interface';\nimport { DynamicFormTypeFieldEnum } from './enums/dynamic-form-type-field.enum';\nimport { CpfValidator } from './validators/cpf.validator';\nimport { CnpjValidator } from './validators/cnpj.validator';\nimport { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';\nimport { FormAbstract } from '../form.abstract';\nimport { debounceTime } from 'rxjs/operators';\nimport { BehaviorSubject } from 'rxjs';\nimport { KoalaDynamicSetValueInterface } from './interfaces/koala.dynamic-set-value.interface';\nimport { AutocompleteSelectedValidator } from './validators/autocomplete-selected.validator';\nimport { KoalaDynamicAutocompleteOptionsInterface } from './interfaces/koala.dynamic-autocomplete-options.interface';\nimport { KoalaDynamicFormShowFieldInterface } from './interfaces/koala.dynamic-form-show-field.interface';\nimport { KoalaDynamicFormService } from './koala.dynamic-form.service';\nimport { KoalaDynamicFormMoreItensShowFieldConfigInterface } from './interfaces/koala.dynamic-form-more-itens-show-field-config.interface';\nimport { ThemePalette } from '@angular/material/core';\nimport { KoalaDynamicFormAutocompleteMultipleConfigInterface } from './interfaces/koala.dynamic-form-autocomplete-multiple-config.interface';\nimport { KoalaDynamicFormConfigInterface } from './interfaces/koala.dynamic-form-config.interface';\nimport { delay } from \"@koalarx/utils/operators/delay\";\nimport { koala } from \"@koalarx/utils\";\nimport { DateMinValidator } from \"./validators/date-min.validator\";\nimport { DateMaxValidator } from \"./validators/date-max.validator\";\nimport { KoalaLanguageHelper } from \"@koalarx/ui/core\";\nimport { randomString } from \"@koalarx/utils/operators/string\";\n\n@Component({\n selector: 'koala-dynamic-form',\n templateUrl: 'dynamic-form.component.html',\n styleUrls: ['dynamic-form.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class DynamicFormComponent extends FormAbstract implements OnInit {\n @Input() form: UntypedFormGroup;\n @Input() formConfig: KoalaDynamicFormFieldInterface[];\n @Input() showFields: BehaviorSubject<KoalaDynamicFormShowFieldInterface[]>;\n @Input() showFieldsMoreItensConfig: KoalaDynamicFormMoreItensShowFieldConfigInterface[];\n @Input() setValues: BehaviorSubject<KoalaDynamicSetValueInterface[]>;\n @Input() tabIndexStart: number = 1;\n\n public controls: UntypedFormArray;\n public typeField = DynamicFormTypeFieldEnum;\n public hoursAndMinutesMask = '00:000';\n public errorMessage = KoalaLanguageHelper;\n public formId = randomString(25, {\n lowercase: true,\n uppercase: true,\n numbers: false,\n specialCharacters: false\n });\n\n constructor(\n private fb: UntypedFormBuilder,\n private dynamicFormService: KoalaDynamicFormService\n ) {\n super(() => this.form);\n }\n\n ngOnInit() {\n if (!this.form.get('formData')) {\n this.form.addControl('formData', this.fb.array([]));\n }\n this.controls = this.form.get('formData') as UntypedFormArray;\n this.formConfig?.forEach((config, indexConfig) => {\n const newFormGroup = this.newControl(config);\n if (config.asyncValidators) {\n newFormGroup.get('value').setAsyncValidators(config.asyncValidators);\n }\n newFormGroup.get('value').updateValueAndValidity();\n if (config.type === DynamicFormTypeFieldEnum.dynamicForm) {\n const formGroupDynamicFormsSubject = newFormGroup.get('dynamicFormConfig').value as BehaviorSubject<KoalaDynamicFormConfigInterface>;\n formGroupDynamicFormsSubject.subscribe(formGroupConfig => {\n if (formGroupConfig) {\n formGroupConfig.form.valueChanges.subscribe(() => {\n if (formGroupConfig.form.valid && (config.valueChanges || this.showFieldsMoreItensConfig)) {\n const value = this.dynamicFormService.emitData(formGroupConfig.form);\n newFormGroup.get('value').setValue(value);\n }\n });\n }\n });\n }\n if (\n config.valueChanges ||\n config.type === DynamicFormTypeFieldEnum.autocomplete ||\n config.type === DynamicFormTypeFieldEnum.dynamicForm ||\n this.showFieldsMoreItensConfig\n ) {\n if (config.type === DynamicFormTypeFieldEnum.autocomplete) {\n const autocompleteOptionsSubject = newFormGroup.get('autocompleteOptions').value as BehaviorSubject<KoalaDynamicAutocompleteOptionsInterface[]>;\n if (autocompleteOptionsSubject) {\n autocompleteOptionsSubject.subscribe(options => newFormGroup.get('autocompleteOptionsFiltered').value.next(options));\n }\n }\n newFormGroup.get('value')\n .valueChanges\n .pipe(debounceTime(300))\n .subscribe(async value => {\n await this.setConfigDynamicForm(newFormGroup);\n if (config.type === DynamicFormTypeFieldEnum.autocomplete) {\n if (\n value && (\n value.hasOwnProperty('value') &&\n value.hasOwnProperty('name') &&\n Object.keys(value).length === 2\n ) || (\n Array.isArray(value) &&\n newFormGroup.get('multiple').value\n )) {\n if (newFormGroup.get('multiple').value) {\n if (Array.isArray(value)) {\n newFormGroup.get('autocompleteSelectedValue').setValue(value);\n newFormGroup.get('value').setValue(value[value.length - 1], {emitEvent: false});\n } else {\n if (this.validateAutocompleteSelect(newFormGroup.get('autocompleteSelectedValue').value, value)) {\n newFormGroup.get('autocompleteSelectedValue').value.push(value);\n }\n }\n\n const autocompleteInput = document.querySelector<HTMLInputElement>(`#${this.formId} input#autocomplete-${newFormGroup.get('name')?.value}`);\n if (autocompleteInput) {\n autocompleteInput.value = '';\n }\n } else {\n newFormGroup.get('autocompleteSelectedValue').setValue(value);\n }\n } else if (!newFormGroup.get('multiple').value) {\n newFormGroup.get('autocompleteSelectedValue').setValue(koala(this.formConfig)\n .array<KoalaDynamicFormFieldInterface>()\n .filter(newFormGroup.get('name').value, 'name')\n .getValue()[0]?.autocompleteDefaultValueOnClear ?? null);\n }\n\n if (config.type === DynamicFormTypeFieldEnum.autocomplete) {\n if (config.autocompleteType === 'all') {\n const autocompleteOptionsSubject = newFormGroup.get('autocompleteOptions').value as BehaviorSubject<KoalaDynamicAutocompleteOptionsInterface[]>;\n newFormGroup.get('autocompleteOptionsFiltered').value.next(this.autocompleteFilter(\n autocompleteOptionsSubject.value,\n value\n ));\n } else if (config.autocompleteType === 'onDemand' && typeof value !== \"object\") {\n const loader = newFormGroup.get('autocompleteLoading').value as BehaviorSubject<boolean>;\n loader.next(true);\n config.autocompleteFilter(value).subscribe(options => {\n newFormGroup.get('autocompleteOptionsFiltered').value.next(options);\n loader.next(false);\n });\n }\n }\n }\n if (config.valueChanges) {\n if (config.type === DynamicFormTypeFieldEnum.autocomplete) {\n config.valueChanges((newFormGroup.get('multiple').value ?\n newFormGroup.get('autocompleteSelectedValue').value.map(item => item.value) :\n newFormGroup.get('autocompleteSelectedValue').value?.value\n ));\n } else {\n config.valueChanges(value);\n }\n }\n });\n }\n this.controls.push(newFormGroup);\n if (config.moreItemsConfig) {\n if (config.moreItemsMinItems > 0) {\n for (let min = 0; min < config.moreItemsMinItems; min++) {\n if (min <= config.moreItemsMaxItems) {\n this.addMoreItem(indexConfig);\n }\n }\n }\n if (config.moreItemsConfig.setValues) {\n config.moreItemsConfig\n .setValues\n .subscribe(async values => {\n if (values.length > 0) {\n values.forEach((itemValue, indexValue) => {\n if (!this.controls.controls[indexConfig].get('moreItemsConfig').value[indexValue]) {\n this.addMoreItem(indexConfig);\n }\n setTimeout(() => {\n this.setValuesOnFields(\n itemValue,\n this.controls.controls[indexConfig].get('moreItemsConfig').value[indexValue].form\n );\n