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