@@ -3,9 +3,13 @@ import { toast } from 'react-toastify'
3
3
4
4
import { FormAction , FormDefinition } from '../form-definition.model'
5
5
import { FormGroup } from '../form-group.model'
6
- import { FormInputModel } from '../form-input.model'
6
+ import { FormInputModel , InputValue } from '../form-input.model'
7
7
8
- export function getInputElement ( formElements : HTMLFormControlsCollection , fieldName : string ) : HTMLInputElement {
8
+ import { FormValue } from './form-value.model'
9
+
10
+ export type ValidationEvent = 'blur' | 'change' | 'submit' | 'initial'
11
+
12
+ export function getInputElement ( formElements : HTMLFormControlsCollection , fieldName : string ) : HTMLInputElement | undefined {
9
13
return formElements . namedItem ( fieldName ) as HTMLInputElement
10
14
}
11
15
@@ -29,29 +33,42 @@ export function getInputModel(inputs: ReadonlyArray<FormInputModel>, fieldName:
29
33
return formField
30
34
}
31
35
32
- export function initializeValues < T > ( inputs : Array < FormInputModel > , formValues ?: T ) : void {
33
- inputs
36
+ export function initializeValues < T extends FormValue > (
37
+ inputs : Array < FormInputModel > ,
38
+ formValues ?: T ,
39
+ ) : void {
40
+
41
+ const filteredInputs : ReadonlyArray < FormInputModel > = inputs
34
42
. filter ( input => ! input . dirty && ! input . touched )
35
- . forEach ( input => {
36
- if ( input . type === 'checkbox' ) {
37
- input . value = input . checked || false
38
- } else {
39
- input . value = ! ! ( formValues as any ) ?. hasOwnProperty ( input . name )
40
- ? ( formValues as any ) [ input . name ]
41
- : undefined
42
- }
43
- } )
43
+
44
+ for ( const input of filteredInputs ) {
45
+ if ( input . type === 'checkbox' ) {
46
+ input . value = input . checked || false
47
+ } else {
48
+ input . value = Object . prototype . hasOwnProperty . call ( formValues , input . name )
49
+ ? ( formValues as { [ id : string ] : InputValue } ) [ input . name ]
50
+ : undefined
51
+ }
52
+ }
44
53
}
45
54
46
- export function onBlur < T > ( event : FormEvent < HTMLInputElement | HTMLTextAreaElement > , inputs : ReadonlyArray < FormInputModel > , formValues ?: T ) : void {
55
+ export function onBlur < T extends FormValue > (
56
+ event : FormEvent < HTMLInputElement | HTMLTextAreaElement > ,
57
+ inputs : ReadonlyArray < FormInputModel > ,
58
+ formValues ?: T ,
59
+ ) : void {
47
60
handleFieldEvent < T > ( event . target as HTMLInputElement | HTMLTextAreaElement , inputs , 'blur' , formValues )
48
61
}
49
62
50
- export function onChange < T > ( event : ChangeEvent < HTMLInputElement | HTMLTextAreaElement > , inputs : ReadonlyArray < FormInputModel > , formValues ?: T ) : void {
63
+ export function onChange < T extends FormValue > (
64
+ event : ChangeEvent < HTMLInputElement | HTMLTextAreaElement > ,
65
+ inputs : ReadonlyArray < FormInputModel > ,
66
+ formValues ?: T ,
67
+ ) : void {
51
68
handleFieldEvent < T > ( event . target as HTMLInputElement | HTMLTextAreaElement , inputs , 'change' , formValues )
52
69
}
53
70
54
- export function onReset ( inputs : ReadonlyArray < FormInputModel > , formValue ?: any ) : void {
71
+ export function onReset < T extends FormValue > ( inputs : ReadonlyArray < FormInputModel > , formValue ?: T ) : void {
55
72
inputs ?. forEach ( inputDef => {
56
73
const typeCastedInput : FormInputModel = inputDef as FormInputModel
57
74
typeCastedInput . dirty = false
@@ -61,7 +78,7 @@ export function onReset(inputs: ReadonlyArray<FormInputModel>, formValue?: any):
61
78
} )
62
79
}
63
80
64
- export async function onSubmitAsync < T > (
81
+ export async function onSubmitAsync < T extends FormValue > (
65
82
action : FormAction ,
66
83
event : FormEvent < HTMLFormElement > ,
67
84
formDef : FormDefinition ,
@@ -93,13 +110,14 @@ export async function onSubmitAsync<T>(
93
110
}
94
111
95
112
// set the properties for the updated T value
113
+ const updatedValue : FormValue = { ...formValue }
96
114
inputs
97
115
. forEach ( field => {
98
- ( formValue as any ) [ field . name ] = field . value
116
+ updatedValue [ field . name ] = field . value
99
117
} )
100
118
101
119
// if there are no dirty fields, don't actually perform the save
102
- const savePromise : Promise < void > = ! dirty ? Promise . resolve ( ) : save ( formValue )
120
+ const savePromise : Promise < void > = ! dirty ? Promise . resolve ( ) : save ( updatedValue as T )
103
121
104
122
return savePromise
105
123
. then ( ( ) => {
@@ -109,13 +127,18 @@ export async function onSubmitAsync<T>(
109
127
toast . success ( safeSuccessMessage )
110
128
onSuccess ?.( )
111
129
} )
112
- . catch ( error => Promise . reject ( error . response ?. data ?. result ?. content || error . message || error ) )
130
+ . catch ( error => Promise . reject ( error . response ?. data ?. result ?. content ?? error . message ?? error ) )
113
131
}
114
132
115
- function handleFieldEvent < T > ( input : HTMLInputElement | HTMLTextAreaElement , inputs : ReadonlyArray < FormInputModel > , event : 'blur' | 'change' , formValues ?: T ) : void {
133
+ function handleFieldEvent < T extends FormValue > (
134
+ input : HTMLInputElement | HTMLTextAreaElement ,
135
+ inputs : ReadonlyArray < FormInputModel > ,
136
+ event : 'blur' | 'change' ,
137
+ formValues ?: T ,
138
+ ) : void {
116
139
117
140
// set the dirty and touched flags on the field
118
- const originalValue : string | undefined = ( formValues as any ) ?. [ input . name ]
141
+ const originalValue : InputValue = formValues ?. [ input . name ]
119
142
120
143
const inputDef : FormInputModel = getInputModel ( inputs , input . name )
121
144
@@ -153,7 +176,11 @@ function handleFieldEvent<T>(input: HTMLInputElement | HTMLTextAreaElement, inpu
153
176
} )
154
177
}
155
178
156
- function validateField ( formInputDef : FormInputModel , formElements : HTMLFormControlsCollection , event : 'blur' | 'change' | 'submit' | 'initial' ) : void {
179
+ function validateField (
180
+ formInputDef : FormInputModel ,
181
+ formElements : HTMLFormControlsCollection ,
182
+ event : 'blur' | 'change' | 'submit' | 'initial' ,
183
+ ) : void {
157
184
158
185
// this is the error the field had before the event took place
159
186
const previousError : string | undefined = formInputDef . error
@@ -162,7 +189,11 @@ function validateField(formInputDef: FormInputModel, formElements: HTMLFormContr
162
189
?. forEach ( validatorFunction => {
163
190
164
191
// if the next error is the same as the previous error, then no need to do anything
165
- const nextError : string | undefined = validatorFunction . validator ( formInputDef . value , formElements , validatorFunction . dependentField )
192
+ const nextError : string | undefined = validatorFunction . validator (
193
+ formInputDef . value ,
194
+ formElements ,
195
+ validatorFunction . dependentField ,
196
+ )
166
197
167
198
if ( previousError === nextError ) {
168
199
return
@@ -186,13 +217,19 @@ function validateField(formInputDef: FormInputModel, formElements: HTMLFormContr
186
217
} )
187
218
}
188
219
189
- export type ValidationEvent = 'blur' | 'change' | 'submit' | 'initial'
220
+ export function validateForm (
221
+ formElements : HTMLFormControlsCollection ,
222
+ event : ValidationEvent ,
223
+ inputs : ReadonlyArray < FormInputModel > ,
224
+ ) : boolean {
225
+
226
+ let hasError : boolean = false
190
227
191
- export function validateForm ( formElements : HTMLFormControlsCollection , event : ValidationEvent , inputs : ReadonlyArray < FormInputModel > ) : boolean {
192
- const errors : ReadonlyArray < FormInputModel > = inputs ?. filter ( formInputDef => {
228
+ for ( const formInputDef of inputs ) {
193
229
formInputDef . dirty = formInputDef . dirty || event === 'submit'
194
230
validateField ( formInputDef , formElements , event )
195
- return ! ! formInputDef . error
196
- } )
197
- return ! errors . length
231
+ hasError = hasError || ! ! formInputDef . error
232
+ }
233
+
234
+ return ! hasError
198
235
}
0 commit comments