Reorganize client shared modules
[oweals/peertube.git] / client / src / app / shared / shared-forms / form-validators / form-validator.service.ts
1 import { FormBuilder, FormControl, FormGroup, ValidatorFn } from '@angular/forms'
2 import { Injectable } from '@angular/core'
3 import { FormReactiveErrors, FormReactiveValidationMessages } from '../form-reactive'
4
5 export type BuildFormValidator = {
6   VALIDATORS: ValidatorFn[],
7   MESSAGES: { [ name: string ]: string }
8 }
9 export type BuildFormArgument = {
10   [ id: string ]: BuildFormValidator | BuildFormArgument
11 }
12 export type BuildFormDefaultValues = {
13   [ name: string ]: string | string[] | BuildFormDefaultValues
14 }
15
16 @Injectable()
17 export class FormValidatorService {
18
19   constructor (
20     private formBuilder: FormBuilder
21   ) {}
22
23   buildForm (obj: BuildFormArgument, defaultValues: BuildFormDefaultValues = {}) {
24     const formErrors: FormReactiveErrors = {}
25     const validationMessages: FormReactiveValidationMessages = {}
26     const group: { [key: string]: any } = {}
27
28     for (const name of Object.keys(obj)) {
29       formErrors[name] = ''
30
31       const field = obj[name]
32       if (this.isRecursiveField(field)) {
33         const result = this.buildForm(field as BuildFormArgument, defaultValues[name] as BuildFormDefaultValues)
34         group[name] = result.form
35         formErrors[name] = result.formErrors
36         validationMessages[name] = result.validationMessages
37
38         continue
39       }
40
41       if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string }
42
43       const defaultValue = defaultValues[name] || ''
44
45       if (field && field.VALIDATORS) group[name] = [ defaultValue, field.VALIDATORS ]
46       else group[name] = [ defaultValue ]
47     }
48
49     const form = this.formBuilder.group(group)
50     return { form, formErrors, validationMessages }
51   }
52
53   updateForm (
54     form: FormGroup,
55     formErrors: FormReactiveErrors,
56     validationMessages: FormReactiveValidationMessages,
57     obj: BuildFormArgument,
58     defaultValues: BuildFormDefaultValues = {}
59   ) {
60     for (const name of Object.keys(obj)) {
61       formErrors[name] = ''
62
63       const field = obj[name]
64       if (this.isRecursiveField(field)) {
65         this.updateForm(
66           form[name],
67           formErrors[name] as FormReactiveErrors,
68           validationMessages[name] as FormReactiveValidationMessages,
69           obj[name] as BuildFormArgument,
70           defaultValues[name] as BuildFormDefaultValues
71         )
72         continue
73       }
74
75       if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string }
76
77       const defaultValue = defaultValues[name] || ''
78
79       if (field && field.VALIDATORS) form.addControl(name, new FormControl(defaultValue, field.VALIDATORS as ValidatorFn[]))
80       else form.addControl(name, new FormControl(defaultValue))
81     }
82   }
83
84   private isRecursiveField (field: any) {
85     return field && typeof field === 'object' && !field.MESSAGES && !field.VALIDATORS
86   }
87 }