diff --git a/src/@episerver/forms-react/src/components/FormBody.tsx b/src/@episerver/forms-react/src/components/FormBody.tsx index 03c4744..3808eec 100644 --- a/src/@episerver/forms-react/src/components/FormBody.tsx +++ b/src/@episerver/forms-react/src/components/FormBody.tsx @@ -68,8 +68,6 @@ export const FormBody = (props: FormBodyProps) => { isProgressiveSubmit.current = true; } - isFormFinalized.current = submitButton?.properties?.finalizeForm || formContext?.currentStepIndex === form.steps.length - 1; - //remove submissions of inactive elements and submissions with undefined value let formSubmissions = (formContext?.formSubmissions ?? []) //only post value of active elements @@ -77,7 +75,7 @@ export const FormBody = (props: FormBodyProps) => { //validate all submission data before submit let formValidationResults = formSubmitter.doValidate(formSubmissions); - dispatchFunctions.dispatchUpdateAllValidation(formValidationResults); + dispatchFunctions.updateAllValidation(formValidationResults); //set focus on the 1st invalid element of current step let invalid = formValidationResults.filter(fv => @@ -85,7 +83,7 @@ export const FormBody = (props: FormBodyProps) => { form.steps[currentStepIndex]?.elements?.some(e => equals(e.key, fv.elementKey)) )[0]?.elementKey; if(!isNullOrEmpty(invalid)){ - dispatchFunctions.dispatchFocusOn(invalid); + dispatchFunctions.updateFocusOn(invalid); isFormFinalized.current = false; return; } @@ -93,13 +91,15 @@ export const FormBody = (props: FormBodyProps) => { let model: FormSubmitModel = { formKey: form.key, locale: form.locale, - isFinalized: isFormFinalized.current, + isFinalized: submitButton?.properties?.finalizeForm || formContext?.currentStepIndex === form.steps.length - 1, partialSubmissionKey: formContext?.submissionKey ?? "", hostedPageUrl: window.location.pathname, submissionData: formSubmissions, accessToken: formContext?.identityInfo?.accessToken } + dispatchFunctions.updateIsSubmitting(true); + formSubmitter.doSubmit(model).then((response: FormSubmitResult)=>{ if(response.success){ message.current = response.messages.map(m => m.message).join("
"); @@ -111,12 +111,13 @@ export const FormBody = (props: FormBodyProps) => { } validateFail.current = response.validationFail; isFormFinalized.current = isSuccess.current = response.success; - dispatchFunctions.dispatchUpdateSubmissionKey(response.submissionKey); + dispatchFunctions.updateSubmissionKey(response.submissionKey); + dispatchFunctions.updateIsSubmitting(false); }); } useEffect(()=>{ - dispatchFunctions.dispatchUpdateIdentity(props.identityInfo); + dispatchFunctions.updateIdentity(props.identityInfo); if(isNullOrEmpty(props.identityInfo?.accessToken) && !form.properties.allowAnonymousSubmission){ statusDisplay.current = "Form__Warning__Message"; statusMessage.current = "You must be logged in to submit this form. If you are logged in and still cannot post, make sure \"Do not track\" in your browser settings is disabled."; diff --git a/src/@episerver/forms-react/src/components/elements/SubmitButtonElementBlock.tsx b/src/@episerver/forms-react/src/components/elements/SubmitButtonElementBlock.tsx index d1bf431..d4fb0b2 100644 --- a/src/@episerver/forms-react/src/components/elements/SubmitButtonElementBlock.tsx +++ b/src/@episerver/forms-react/src/components/elements/SubmitButtonElementBlock.tsx @@ -1,7 +1,6 @@ import { SubmitButton, isNullOrEmpty } from "@episerver/forms-sdk"; import React, { useMemo } from "react"; import { useElement } from "../../hooks/useElement"; -import ElementWrapper from "./shared/ElementWrapper"; interface SubmitButtonElementBlockProps{ element: SubmitButton @@ -10,7 +9,7 @@ interface SubmitButtonElementBlockProps{ export const SubmitButtonElementBlock = (props: SubmitButtonElementBlockProps) => { const { element } = props; const { elementContext } = useElement(element); - const { isVisible, extraAttr, validatorClasses } = elementContext; + const { isVisible, extraAttr, validatorClasses, elementRef } = elementContext; //TODO: Need to get submittable status from API const buttonDisableState = false; @@ -25,6 +24,7 @@ export const SubmitButtonElementBlock = (props: SubmitButtonElementBlockProps) = ? `Form__Element FormExcludeDataRebind FormSubmitButton ${validatorClasses}` : `Form__Element FormExcludeDataRebind FormSubmitButton FormImageSubmitButton ${validatorClasses}` } + ref={elementRef} > {isNullOrEmpty(element.properties.image) ? element.properties.label : ( {element.properties.label} diff --git a/src/@episerver/forms-react/src/context/dispatchFunctions.ts b/src/@episerver/forms-react/src/context/dispatchFunctions.ts index baaf0a1..26f8bf6 100644 --- a/src/@episerver/forms-react/src/context/dispatchFunctions.ts +++ b/src/@episerver/forms-react/src/context/dispatchFunctions.ts @@ -7,7 +7,7 @@ export class DispatchFunctions { this._dispatch = dispatch; } - dispatchUpdateValidation = (elementKey: string, validationResults: ElementValidationResult[]) => { + updateValidation = (elementKey: string, validationResults: ElementValidationResult[]) => { this._dispatch({ type: ActionType.UpdateValidation, elementKey: elementKey, @@ -15,14 +15,14 @@ export class DispatchFunctions { }); } - dispatchUpdateAllValidation = (formValidationResults: FormValidationResult[]) => { + updateAllValidation = (formValidationResults: FormValidationResult[]) => { this._dispatch({ type: ActionType.UpdateAllValidation, formValidationResults }); } - dispatchUpdateValue = (elementKey: string, value: any) => { + updateValue = (elementKey: string, value: any) => { this._dispatch({ type: ActionType.UpdateValue, elementKey: elementKey, @@ -30,20 +30,20 @@ export class DispatchFunctions { }); } - dispatchUpdateDependencies = (dependencyInactiveElements: string[]) => { + updateDependencies = (dependencyInactiveElements: string[]) => { this._dispatch({ type: ActionType.UpdateDependencies, dependencyInactiveElements }); } - dispatchResetedForm = () => { + resetedForm = () => { this._dispatch({ type: ActionType.ResetedForm }); } - dispatchResetForm = (formContainer: FormContainer) => { + resetForm = (formContainer: FormContainer) => { this._dispatch({ type: ActionType.ResetForm, formState: { @@ -53,31 +53,38 @@ export class DispatchFunctions { }); } - dispatchFocusOn = (focusOn: string) => { + updateFocusOn = (focusOn: string) => { this._dispatch({ type: ActionType.UpdateFocusOn, focusOn }); } - dispatchUpdateIdentity = (identityInfo?: IdentityInfo) => { + updateIdentity = (identityInfo?: IdentityInfo) => { this._dispatch({ type: ActionType.UpdateIdentityInfo, identityInfo }); } - dispatchUpdateSubmissionKey = (submissionKey?: string) => { + updateSubmissionKey = (submissionKey?: string) => { this._dispatch({ type: ActionType.UpdateSubmissionKey, submissionKey }); } - dispatchUpdateCurrentStepIndex = (currentStepIndex?: number) => { + updateCurrentStepIndex = (currentStepIndex?: number) => { this._dispatch({ type: ActionType.UpdateCurrentStepIndex, currentStepIndex }); } + + updateIsSubmitting = (isSubmitting?: boolean) => { + this._dispatch({ + type: ActionType.UpdateIsSubmitting, + isSubmitting + }); + } } \ No newline at end of file diff --git a/src/@episerver/forms-react/src/context/reducer.ts b/src/@episerver/forms-react/src/context/reducer.ts index 0987259..e192fc6 100644 --- a/src/@episerver/forms-react/src/context/reducer.ts +++ b/src/@episerver/forms-react/src/context/reducer.ts @@ -13,7 +13,8 @@ export enum ActionType { UpdateFocusOn = "UpdateFocusOn", UpdateIdentityInfo = "UpdateIdentityInfo", UpdateSubmissionKey = "UpdateSubmissionKey", - UpdateCurrentStepIndex = "UpdateCurrentStepIndex" + UpdateCurrentStepIndex = "UpdateCurrentStepIndex", + UpdateIsSubmitting = "UpdateIsSubmitting" } export function formReducer(formState: FormState, action: any) { @@ -84,6 +85,12 @@ export function formReducer(formState: FormState, action: any) { currentStepIndex: action.currentStepIndex } as FormState } + case ActionType.UpdateIsSubmitting: { + return { + ...formState, + isSubmitting: action.isSubmitting + } as FormState + } default: { return formState; } diff --git a/src/@episerver/forms-react/src/hooks/useElement.ts b/src/@episerver/forms-react/src/hooks/useElement.ts index 6c9569d..3b93425 100644 --- a/src/@episerver/forms-react/src/hooks/useElement.ts +++ b/src/@episerver/forms-react/src/hooks/useElement.ts @@ -72,7 +72,7 @@ export const useElement = (element: FormElementBase) => { useEffect(()=>{ if(formContext?.isReset){ //update form state - dispatchFuncs.dispatchResetedForm(); + dispatchFuncs.resetedForm(); } },[formContext?.isReset]); @@ -103,7 +103,7 @@ export const useElement = (element: FormElementBase) => { else { !isInArray(element.key, inactives) && inactives.push(element.key); } - dispatchFuncs.dispatchUpdateDependencies(inactives); + dispatchFuncs.updateDependencies(inactives); },[formContext?.formSubmissions]); //focus on element if validate fail before submitting @@ -111,10 +111,17 @@ export const useElement = (element: FormElementBase) => { let focusOn = formContext?.focusOn ?? ""; if(equals(focusOn, element.key)){ elementRef.current && elementRef.current.focus(); - dispatchFuncs.dispatchFocusOn(""); + dispatchFuncs.updateFocusOn(""); } },[formContext?.focusOn]); + //disable submit button when form submitting + useEffect(()=>{ + if(equals(element.contentType, "SubmitButtonElementBlock")){ + elementRef.current.disabled = formContext?.isSubmitting ?? false; + } + },[formContext?.isSubmitting]) + const handleChange = (e: any) => { const { name, value: inputValue, type, checked, files } = e.target; let submissionValue = inputValue; @@ -138,11 +145,11 @@ export const useElement = (element: FormElementBase) => { if (/file/.test(type)) { submissionValue = files; let validationResults = formValidation.validate(files) - dispatchFuncs.dispatchUpdateValidation(element.key, validationResults); + dispatchFuncs.updateValidation(element.key, validationResults); } //update form context - dispatchFuncs.dispatchUpdateValue(element.key, submissionValue); + dispatchFuncs.updateValue(element.key, submissionValue); } const handleBlur = (e: any) => { @@ -150,11 +157,11 @@ export const useElement = (element: FormElementBase) => { let validationResults = formValidation.validate(value); //update form context - dispatchFuncs.dispatchUpdateValidation(element.key, validationResults); + dispatchFuncs.updateValidation(element.key, validationResults); } const handleReset = () => { - dispatchFuncs.dispatchResetForm(formContext?.formContainer ?? {} as FormContainer); + dispatchFuncs.resetForm(formContext?.formContainer ?? {} as FormContainer); } return { diff --git a/src/@episerver/forms-sdk/src/models/states/FormState.ts b/src/@episerver/forms-sdk/src/models/states/FormState.ts index f4fbbf9..5224c7d 100644 --- a/src/@episerver/forms-sdk/src/models/states/FormState.ts +++ b/src/@episerver/forms-sdk/src/models/states/FormState.ts @@ -18,4 +18,5 @@ export interface FormState { identityInfo?: IdentityInfo submissionKey?: string currentStepIndex: number + isSubmitting?: boolean } \ No newline at end of file