Created
August 31, 2023 10:17
-
-
Save genki/632d57ffc53a136521f486867756469b to your computer and use it in GitHub Desktop.
`submit(formStore, onSubmit$)` method that enables the `modular-forms/qwik` to submit the form equivalent to simulate the manual submit.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { | |
FormStore, FieldValues, ResponseData, FormErrors, FieldPath, FieldArrayPath, | |
SetResponseOptions, | |
} from '@modular-forms/qwik'; | |
import { | |
getValues, validate, setResponse, FormError, setError, | |
} from '@modular-forms/qwik'; | |
import { type Maybe } from '~/utils'; | |
type ErrorResponseOptions = SetResponseOptions & | |
Partial<{ | |
shouldActive: boolean; | |
}>; | |
export type SetErrorOptions = Partial<{ | |
shouldActive: boolean; | |
shouldTouched: boolean; | |
shouldDirty: boolean; | |
shouldFocus: boolean; | |
}>; | |
export function getFieldStore< | |
TFieldValues extends FieldValues, | |
TFieldName extends FieldPath<TFieldValues> | |
>( | |
form: FormStore<FieldValues, ResponseData>, | |
name: TFieldName | |
) { | |
return form.internal.fields[name]; | |
} | |
export function getFieldArrayStore< | |
TFieldValues extends FieldValues, | |
TFieldName extends FieldPath<TFieldValues> | |
>( | |
form: FormStore<FieldValues, ResponseData>, | |
name: TFieldName | |
) { | |
return form.internal.fieldArrays[name]; | |
} | |
function setFieldErrors( | |
form: FormStore<FieldValues, ResponseData>, | |
errors: FormErrors<FieldValues>, | |
options: SetErrorOptions | |
) { | |
Object.entries(errors).forEach(([name, error]) => { | |
if (!error) return; | |
setError(form, name, error, { ...options, shouldFocus: false }); | |
}); | |
} | |
function setErrorResponse( | |
form: FormStore<FieldValues, ResponseData>, | |
formErrors: FormErrors<FieldValues>, | |
{ duration, shouldActive = true }: ErrorResponseOptions | |
): void { | |
// Combine errors that were not set for any field or field array into one | |
// general form error response message | |
const message = Object.entries<Maybe<string>>(formErrors) | |
.reduce<string[]>((errors, [name, error]) => { | |
if ( | |
[ | |
getFieldStore(form, name as FieldPath<FieldValues>), | |
getFieldArrayStore(form, name as FieldArrayPath<FieldValues>), | |
].every( | |
(fieldOrFieldArray) => | |
!fieldOrFieldArray || (shouldActive && !fieldOrFieldArray.active) | |
) | |
) { | |
errors.push(error!); | |
} | |
return errors; | |
}, []) | |
.join(' '); | |
// If there is a error message, set it as form response | |
if (message) { | |
setResponse(form, { status: 'error', message }, { duration }); | |
} | |
} | |
type SubmitOptions = { | |
keepResponse?: boolean; | |
duration?: number; | |
names?: string[]; | |
shouldActive?: boolean; | |
}; | |
export async function submit( | |
form: FormStore<FieldValues, ResponseData>, | |
onSubmit$: any, | |
options:SubmitOptions = {} | |
) { | |
// Reset response if it is not to be kept | |
if (!options.keepResponse) form.response = {}; | |
// Increase submit count and set submitted and submitting to "true" | |
form.submitCount++; | |
form.submitted = true; | |
form.submitting = true; | |
// Try to run submit actions if form is valid | |
try { | |
if (await validate(form, options)) { | |
// Get current values of form | |
const values = getValues(form, options); | |
// Run submit actions of form | |
const result = await onSubmit$?.(values as FieldValues); | |
// Set form action result if necessary | |
if (result?.value) { | |
const { errors, response } = result.value; | |
setFieldErrors(form, errors, { ...options, shouldFocus: false }); | |
if (Object.keys(response).length) { | |
setResponse(form, response, options); | |
} else { | |
setErrorResponse(form, errors, options); | |
} | |
} | |
} | |
// If an error occurred, set error to fields and response | |
} catch (error: any) { | |
if (error instanceof FormError) { | |
setFieldErrors(form, error.errors, { ...options, shouldFocus: false }); | |
} | |
if (!(error instanceof FormError) || error.message) { | |
setResponse( | |
form, | |
{ | |
status: 'error', | |
message: error?.message || 'An unknown error has occurred.', | |
}, | |
options | |
); | |
} | |
// Finally set submitting back to "false" | |
} finally { | |
form.submitting = false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment