diff options
Diffstat (limited to 'client/src/app/shared')
4 files changed, 62 insertions, 21 deletions
diff --git a/client/src/app/shared/forms/form-reactive.ts b/client/src/app/shared/forms/form-reactive.ts index 0bb7d25e6..2d0e8359f 100644 --- a/client/src/app/shared/forms/form-reactive.ts +++ b/client/src/app/shared/forms/form-reactive.ts | |||
@@ -1,11 +1,9 @@ | |||
1 | import { FormGroup } from '@angular/forms' | 1 | import { FormGroup } from '@angular/forms' |
2 | import { BuildFormArgument, BuildFormDefaultValues, FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' | 2 | import { BuildFormArgument, BuildFormDefaultValues, FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' |
3 | 3 | ||
4 | export type FormReactiveErrors = { [ id: string ]: string } | 4 | export type FormReactiveErrors = { [ id: string ]: string | FormReactiveErrors } |
5 | export type FormReactiveValidationMessages = { | 5 | export type FormReactiveValidationMessages = { |
6 | [ id: string ]: { | 6 | [ id: string ]: { [ name: string ]: string } | FormReactiveValidationMessages |
7 | [ name: string ]: string | ||
8 | } | ||
9 | } | 7 | } |
10 | 8 | ||
11 | export abstract class FormReactive { | 9 | export abstract class FormReactive { |
@@ -23,29 +21,49 @@ export abstract class FormReactive { | |||
23 | this.formErrors = formErrors | 21 | this.formErrors = formErrors |
24 | this.validationMessages = validationMessages | 22 | this.validationMessages = validationMessages |
25 | 23 | ||
26 | this.form.valueChanges.subscribe(() => this.onValueChanged(false)) | 24 | this.form.valueChanges.subscribe(() => this.onValueChanged(this.form, this.formErrors, this.validationMessages, false)) |
25 | } | ||
26 | |||
27 | protected forceCheck () { | ||
28 | return this.onValueChanged(this.form, this.formErrors, this.validationMessages, true) | ||
29 | } | ||
30 | |||
31 | protected check () { | ||
32 | return this.onValueChanged(this.form, this.formErrors, this.validationMessages, false) | ||
27 | } | 33 | } |
28 | 34 | ||
29 | protected onValueChanged (forceCheck = false) { | 35 | private onValueChanged ( |
30 | for (const field in this.formErrors) { | 36 | form: FormGroup, |
37 | formErrors: FormReactiveErrors, | ||
38 | validationMessages: FormReactiveValidationMessages, | ||
39 | forceCheck = false | ||
40 | ) { | ||
41 | for (const field of Object.keys(formErrors)) { | ||
42 | if (formErrors[field] && typeof formErrors[field] === 'object') { | ||
43 | this.onValueChanged( | ||
44 | form.controls[field] as FormGroup, | ||
45 | formErrors[field] as FormReactiveErrors, | ||
46 | validationMessages[field] as FormReactiveValidationMessages, | ||
47 | forceCheck | ||
48 | ) | ||
49 | continue | ||
50 | } | ||
51 | |||
31 | // clear previous error message (if any) | 52 | // clear previous error message (if any) |
32 | this.formErrors[ field ] = '' | 53 | formErrors[ field ] = '' |
33 | const control = this.form.get(field) | 54 | const control = form.get(field) |
34 | 55 | ||
35 | if (control.dirty) this.formChanged = true | 56 | if (control.dirty) this.formChanged = true |
36 | 57 | ||
37 | // Don't care if dirty on force check | 58 | // Don't care if dirty on force check |
38 | const isDirty = control.dirty || forceCheck === true | 59 | const isDirty = control.dirty || forceCheck === true |
39 | if (control && isDirty && !control.valid) { | 60 | if (control && isDirty && !control.valid) { |
40 | const messages = this.validationMessages[ field ] | 61 | const messages = validationMessages[ field ] |
41 | for (const key in control.errors) { | 62 | for (const key in control.errors) { |
42 | this.formErrors[ field ] += messages[ key ] + ' ' | 63 | formErrors[ field ] += messages[ key ] + ' ' |
43 | } | 64 | } |
44 | } | 65 | } |
45 | } | 66 | } |
46 | } | 67 | } |
47 | 68 | ||
48 | protected forceCheck () { | ||
49 | return this.onValueChanged(true) | ||
50 | } | ||
51 | } | 69 | } |
diff --git a/client/src/app/shared/forms/form-validators/form-validator.service.ts b/client/src/app/shared/forms/form-validators/form-validator.service.ts index 19a8bef25..249fdf119 100644 --- a/client/src/app/shared/forms/form-validators/form-validator.service.ts +++ b/client/src/app/shared/forms/form-validators/form-validator.service.ts | |||
@@ -7,10 +7,10 @@ export type BuildFormValidator = { | |||
7 | MESSAGES: { [ name: string ]: string } | 7 | MESSAGES: { [ name: string ]: string } |
8 | } | 8 | } |
9 | export type BuildFormArgument = { | 9 | export type BuildFormArgument = { |
10 | [ id: string ]: BuildFormValidator | 10 | [ id: string ]: BuildFormValidator | BuildFormArgument |
11 | } | 11 | } |
12 | export type BuildFormDefaultValues = { | 12 | export type BuildFormDefaultValues = { |
13 | [ name: string ]: string | string[] | 13 | [ name: string ]: string | string[] | BuildFormDefaultValues |
14 | } | 14 | } |
15 | 15 | ||
16 | @Injectable() | 16 | @Injectable() |
@@ -29,7 +29,16 @@ export class FormValidatorService { | |||
29 | formErrors[name] = '' | 29 | formErrors[name] = '' |
30 | 30 | ||
31 | const field = obj[name] | 31 | const field = obj[name] |
32 | if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES | 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 } | ||
33 | 42 | ||
34 | const defaultValue = defaultValues[name] || '' | 43 | const defaultValue = defaultValues[name] || '' |
35 | 44 | ||
@@ -52,13 +61,27 @@ export class FormValidatorService { | |||
52 | formErrors[name] = '' | 61 | formErrors[name] = '' |
53 | 62 | ||
54 | const field = obj[name] | 63 | const field = obj[name] |
55 | if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES | 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 } | ||
56 | 76 | ||
57 | const defaultValue = defaultValues[name] || '' | 77 | const defaultValue = defaultValues[name] || '' |
58 | 78 | ||
59 | if (field && field.VALIDATORS) form.addControl(name, new FormControl(defaultValue, field.VALIDATORS)) | 79 | if (field && field.VALIDATORS) form.addControl(name, new FormControl(defaultValue, field.VALIDATORS as ValidatorFn[])) |
60 | else form.addControl(name, new FormControl(defaultValue)) | 80 | else form.addControl(name, new FormControl(defaultValue)) |
61 | } | 81 | } |
62 | } | 82 | } |
63 | 83 | ||
84 | private isRecursiveField (field: any) { | ||
85 | return field && typeof field === 'object' && !field.MESSAGES && !field.VALIDATORS | ||
86 | } | ||
64 | } | 87 | } |
diff --git a/client/src/app/shared/misc/help.component.scss b/client/src/app/shared/misc/help.component.scss index 6a5c3b1fa..047e53fab 100644 --- a/client/src/app/shared/misc/help.component.scss +++ b/client/src/app/shared/misc/help.component.scss | |||
@@ -12,7 +12,7 @@ | |||
12 | } | 12 | } |
13 | 13 | ||
14 | /deep/ { | 14 | /deep/ { |
15 | .popover-help.popover { | 15 | .help-popover { |
16 | max-width: 300px; | 16 | max-width: 300px; |
17 | 17 | ||
18 | .popover-body { | 18 | .popover-body { |
diff --git a/client/src/app/shared/user-subscription/remote-subscribe.component.ts b/client/src/app/shared/user-subscription/remote-subscribe.component.ts index 49722ce40..ba2a45df1 100644 --- a/client/src/app/shared/user-subscription/remote-subscribe.component.ts +++ b/client/src/app/shared/user-subscription/remote-subscribe.component.ts | |||
@@ -29,7 +29,7 @@ export class RemoteSubscribeComponent extends FormReactive implements OnInit { | |||
29 | } | 29 | } |
30 | 30 | ||
31 | onValidKey () { | 31 | onValidKey () { |
32 | this.onValueChanged() | 32 | this.check() |
33 | if (!this.form.valid) return | 33 | if (!this.form.valid) return |
34 | 34 | ||
35 | this.formValidated() | 35 | this.formValidated() |