1 import { Injectable } from '@angular/core'
2 import { AsyncValidatorFn, FormArray, FormBuilder, FormControl, FormGroup, ValidatorFn } from '@angular/forms'
3 import { objectKeysTyped } from '@shared/core-utils'
4 import { BuildFormArgument, BuildFormDefaultValues } from '../form-validators/form-validator.model'
5 import { FormReactiveErrors, FormReactiveValidationMessages } from './form-reactive.service'
8 export class FormValidatorService {
11 private formBuilder: FormBuilder
14 buildForm (obj: BuildFormArgument, defaultValues: BuildFormDefaultValues = {}) {
15 const formErrors: FormReactiveErrors = {}
16 const validationMessages: FormReactiveValidationMessages = {}
17 const group: { [key: string]: any } = {}
19 for (const name of Object.keys(obj)) {
22 const field = obj[name]
23 if (this.isRecursiveField(field)) {
24 const result = this.buildForm(field as BuildFormArgument, defaultValues[name] as BuildFormDefaultValues)
25 group[name] = result.form
26 formErrors[name] = result.formErrors
27 validationMessages[name] = result.validationMessages
32 if (field?.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string }
34 const defaultValue = defaultValues[name] ?? ''
36 if (field?.VALIDATORS) group[name] = [ defaultValue, field.VALIDATORS ]
37 else group[name] = [ defaultValue ]
40 const form = this.formBuilder.group(group)
41 return { form, formErrors, validationMessages }
46 formErrors: FormReactiveErrors,
47 validationMessages: FormReactiveValidationMessages,
48 obj: BuildFormArgument,
49 defaultValues: BuildFormDefaultValues = {}
51 for (const name of objectKeysTyped(obj)) {
54 const field = obj[name]
55 if (this.isRecursiveField(field)) {
59 formErrors[name] as FormReactiveErrors,
60 validationMessages[name] as FormReactiveValidationMessages,
61 obj[name] as BuildFormArgument,
62 defaultValues[name] as BuildFormDefaultValues
67 if (field?.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string }
69 const defaultValue = defaultValues[name] || ''
73 new FormControl(defaultValue, field?.VALIDATORS as ValidatorFn[], field?.ASYNC_VALIDATORS as AsyncValidatorFn[])
78 updateTreeValidity (group: FormGroup | FormArray): void {
79 for (const key of Object.keys(group.controls)) {
81 const abstractControl = (group.controls as any)[key] as FormControl
83 if (abstractControl instanceof FormGroup || abstractControl instanceof FormArray) {
84 this.updateTreeValidity(abstractControl)
86 abstractControl.updateValueAndValidity({ emitEvent: false })
91 private isRecursiveField (field: any) {
92 return field && typeof field === 'object' && !field.MESSAGES && !field.VALIDATORS