FunctionOneBlinkFormControlled

Similar to OneBlinkForm, however requires props to control the definition and submission values.

import React from 'react'
import ReactDOM from 'react-dom'
import { FormTypes } from '@oneblink/types'
import {
OneBlinkAppsError,
draftService,
submissionService,
} from '@oneblink/apps'
import {
IsOfflineContextProvider,
OneBlinkFormControlled,
useIsMounted,
useFormSubmissionState,
} from '@oneblink/apps-react'
import '@oneblink/apps-react/dist/styles.css'

const captchaSiteKey = 'ENTER_YOUR_SITE_KEY_HERE'
const googleMapsApiKey = 'ENTER_YOUR_MAPS_API_KEY_HERE'
const formsAppId = 1
const form: FormTypes.Form = {
id: 1,
name: 'Name of Form',
description: '',
organisationId: 'abc123',
formsAppEnvironmentId: 1,
formsAppIds: [],
elements: [],
isAuthenticated: false,
isMultiPage: false,
isInfoPage: false,
publishStartDate: null,
publishEndDate: null,
postSubmissionAction: 'FORMS_LIBRARY',
submissionEvents: [],
tags: [],
}
const initialSubmission: Record<string, unknown> = {
data: 1,
}

function FormContainer() {
const isMounted = useIsMounted()

const [{ definition, submission }, setFormSubmission] =
useFormSubmissionState(form, initialSubmission)

const [{ isSavingDraft, saveDraftError }, setSaveDraftState] =
React.useState({
isSavingDraft: false,
saveDraftError: null,
})

const [
{ isSubmitting, submitError, formSubmissionResult },
setSubmitState,
] = React.useState({
formSubmissionResult: null,
isSubmitting: false,
submitError: null,
})

const handleSubmit = React.useCallback(
async (newFormSubmission: FormTypes.NewFormSubmission) => {
const formSubmission: FormSubmission = Object.assign(
{},
newFormSubmission,
{
formsAppId,
jobId: null,
externalId: null,
draftId: null,
preFillFormDataId: null,
},
)

setSubmitState({
formSubmissionResult: null,
submitError: null,
isSubmitting: true,
})

try {
const newFormSubmissionResult = await submissionService.submit({
formSubmission,
})
if (
newFormSubmissionResult.isOffline &&
!newFormSubmissionResult.isInPendingQueue
) {
throw new OneBlinkAppsError(
'You cannot submit this form while offline, please try again when connectivity is restored.',
{
isOffline: true,
},
)
}

if (isMounted.current) {
setSubmitState({
formSubmissionResult: newFormSubmissionResult,
isSubmitting: false,
submitError: null,
})
}
} catch (error) {
if (isMounted.current) {
setSubmitState({
formSubmissionResult: null,
isSubmitting: false,
submitError: error,
})
}
}
},
[isMounted],
)

const handleSaveDraft = React.useCallback(
async (newDraftSubmission: FormTypes.NewDraftSubmission) => {
const draftSubmission: FormTypes.DraftSubmission = {
...newDraftSubmission,
formsAppId,
}
setSaveDraftState({
saveDraftError: null,
isSavingDraft: true,
})

try {
await draftService.addDraft(
{
title: form.name,
formId: form.id,
externalId: null,
jobId: null,
},
draftSubmission,
)

if (isMounted.current) {
setSaveDraftState({
saveDraftError: null,
isSavingDraft: false,
})
}
} catch (error) {
if (isMounted.current) {
setSaveDraftState({
saveDraftError: error,
isSavingDraft: false,
})
}
}
},
[isMounted],
)

const handleCancel = React.useCallback(() => {
// handle cancel here...
}, [])

if (isSubmitting) {
// Render submitting animation/loading
}

if (submitError) {
// Render error while submitting
}

if (isSavingDraft) {
// Render saving draft animation/loading
}

if (saveDraftError) {
// Render error while saving draft
}

if (formSubmissionResult) {
// Render submission success
}

return (
<OneBlinkFormControlled
captchaSiteKey={captchaSiteKey}
googleMapsApiKey={googleMapsApiKey}
formsAppId={formsAppId}
definition={definition}
submission={submission}
setFormSubmission={setFormSubmission}
onCancel={handleCancel}
onSubmit={handleSubmit}
onSaveDraft={handleSaveDraft}
/>
)
}

function App() {
return (
<IsOfflineContextProvider>
<FormContainer />
</IsOfflineContextProvider>
)
}

const root = document.getElementById('root')
if (root) {
ReactDOM.render(<App />, root)
}

The OneBlinkAutoSaveForm component does not offer props to allow for a controlled form (i.e. having access to submission and definition values). To implement a controlled version of the <OneBlinkAutoSaveForm /> component, use the example component below.

import * as React from 'react'
import {
OneBlinkAutoSaveForm,
OneBlinkFormControlled,
useFormSubmissionAutoSaveState,
} from '@oneblink/apps-react'

function OneBlinkAutoSaveFormControlled({
form,
initialSubmission,
autoSaveKey,
onCancel,
onSubmit,
onSaveDraft,
...props
}: React.ComponentProps<typeof OneBlinkAutoSaveForm>) {
const {
definition,
submission,
isLoadingAutoSaveSubmission,
isAutoSaveSubmissionAvailable,
startNewSubmission,
continueAutoSaveSubmission,
handleSubmit,
handleCancel,
handleSaveDraft,
setFormSubmission,
} = useFormSubmissionAutoSaveState({
form,
initialSubmission,
autoSaveKey,
onCancel,
onSubmit,
onSaveDraft,
})

// This is just an example of how you could intercept
// the change event when a user enters/selects a value
// on the form.
const customSetFormSubmission = React.useCallback(
(formSubmission) => {
setFormSubmission((currentFormSubmission) => {
const newFormSubmission =
typeof formSubmission === 'function'
? formSubmission(currentFormSubmission)
: formSubmission

// This is where you can access the updated
// submission data or form definition.
// You could even change the form definition
// programmatically based on user inputs.
console.log(
'A change has occurred to the submission',
newFormSubmission.submission,
)
newFormSubmission.definition.isInfoPage =
!newFormSubmission.submission.doesTheUserNeedToSubmit

return newFormSubmission
})
},
[setFormSubmission],
)

if (isLoadingAutoSaveSubmission) {
return <p>Checking for auto save data...</p>
}

if (isAutoSaveSubmissionAvailable) {
return (
<>
<p>Do you want to use the auto save data?</p>
<button onClick={startNewSubmission}>No, start again</button>
<button onClick={continueAutoSaveSubmission}>
Yes, continue
</button>
</>
)
}

return (
<OneBlinkFormControlled
{...props}
submission={submission}
definition={definition}
onCancel={handleCancel}
onSubmit={handleSubmit}
onSaveDraft={handleSaveDraft}
setFormSubmission={customSetFormSubmission}
/>
)
}

export default React.memo(OneBlinkAutoSaveFormControlled)
  • NOTE: Exotic components are not callable.

    Parameters

    • props: OneBlinkReadOnlyFormProps & {
          abnLookupAuthenticationGuid?: string;
          attachmentRetentionInDays?: number;
          buttons?: {
              cancel?: ButtonConfiguration;
              cancelPromptNo?: ButtonConfiguration;
              cancelPromptYes?: ButtonConfiguration;
              saveDraft?: ButtonConfiguration;
              submit?: ButtonConfiguration;
          };
          captchaSiteKey?: string;
          captchaType?: CaptchaType;
          disabled?: boolean;
          handleNavigateAway?: (() => unknown);
          isInfoPage?: "YES" | "NO" | "CALCULATED";
          isPendingQueueEnabled: boolean;
          isPreview?: boolean;
          navigableValidationErrorsNotificationSettings?: {
              navigationTopOffset?: number;
              scrollableContainerId?: string;
          };
          onCancel: (() => unknown);
          onSaveDraft?: ((newDraftSubmission: NewDraftSubmission) => unknown);
          onSubmit: ((newFormSubmission: NewFormSubmission) => unknown);
          onUploadAttachment?: ((options: UploadAttachmentConfiguration, abortSignal?: AbortSignal) => Promise<FormSubmissionAttachment>);
          shouldUseNavigableValidationErrorsNotification?: boolean;
      } & OneBlinkFormControlledProps

    Returns null | ReactElement<any, string | JSXElementConstructor<any>>

Properties

$$typeof: symbol
displayName?: string