@@ -3,9 +3,13 @@ import { toast } from 'react-toastify'
33
44import { FormAction , FormDefinition } from '../form-definition.model'
55import { FormGroup } from '../form-group.model'
6- import { FormInputModel } from '../form-input.model'
6+ import { FormInputModel , InputValue } from '../form-input.model'
77
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 {
913 return formElements . namedItem ( fieldName ) as HTMLInputElement
1014}
1115
@@ -29,29 +33,43 @@ export function getInputModel(inputs: ReadonlyArray<FormInputModel>, fieldName:
2933 return formField
3034}
3135
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
3442 . 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 ]
4151 : undefined
42- }
43- } )
52+ }
53+ }
4454}
4555
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 {
4761 handleFieldEvent < T > ( event . target as HTMLInputElement | HTMLTextAreaElement , inputs , 'blur' , formValues )
4862}
4963
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 {
5169 handleFieldEvent < T > ( event . target as HTMLInputElement | HTMLTextAreaElement , inputs , 'change' , formValues )
5270}
5371
54- export function onReset ( inputs : ReadonlyArray < FormInputModel > , formValue ?: any ) : void {
72+ export function onReset < T extends FormValue > ( inputs : ReadonlyArray < FormInputModel > , formValue ?: T ) : void {
5573 inputs ?. forEach ( inputDef => {
5674 const typeCastedInput : FormInputModel = inputDef as FormInputModel
5775 typeCastedInput . dirty = false
@@ -61,7 +79,7 @@ export function onReset(inputs: ReadonlyArray<FormInputModel>, formValue?: any):
6179 } )
6280}
6381
64- export async function onSubmitAsync < T > (
82+ export async function onSubmitAsync < T extends FormValue > (
6583 action : FormAction ,
6684 event : FormEvent < HTMLFormElement > ,
6785 formDef : FormDefinition ,
@@ -93,13 +111,14 @@ export async function onSubmitAsync<T>(
93111 }
94112
95113 // set the properties for the updated T value
114+ const updatedValue : FormValue = { ...formValue }
96115 inputs
97116 . forEach ( field => {
98- ( formValue as any ) [ field . name ] = field . value
117+ updatedValue [ field . name ] = field . value
99118 } )
100119
101120 // 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 )
103122
104123 return savePromise
105124 . then ( ( ) => {
@@ -109,13 +128,18 @@ export async function onSubmitAsync<T>(
109128 toast . success ( safeSuccessMessage )
110129 onSuccess ?.( )
111130 } )
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 ) )
113132}
114133
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 {
116140
117141 // 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 ]
119143
120144 const inputDef : FormInputModel = getInputModel ( inputs , input . name )
121145
@@ -153,7 +177,11 @@ function handleFieldEvent<T>(input: HTMLInputElement | HTMLTextAreaElement, inpu
153177 } )
154178}
155179
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 {
157185
158186 // this is the error the field had before the event took place
159187 const previousError : string | undefined = formInputDef . error
@@ -162,7 +190,11 @@ function validateField(formInputDef: FormInputModel, formElements: HTMLFormContr
162190 ?. forEach ( validatorFunction => {
163191
164192 // 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+ )
166198
167199 if ( previousError === nextError ) {
168200 return
@@ -186,13 +218,19 @@ function validateField(formInputDef: FormInputModel, formElements: HTMLFormContr
186218 } )
187219}
188220
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
190228
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 ) {
193230 formInputDef . dirty = formInputDef . dirty || event === 'submit'
194231 validateField ( formInputDef , formElements , event )
195- return ! ! formInputDef . error
196- } )
197- return ! errors . length
232+ hasError = hasError || ! ! formInputDef . error
233+ }
234+
235+ return ! hasError
198236}
0 commit comments