To implement a custom wizard form, you can use the common wizard component. This component provides basic functionality such as branching, submitting only visited values, etc. Also, this wizard is used in all of our provided mappers.

When implementing custom wizard, please keep it under wizard component key so the schema validator won't expect that nested fields (=wizard steps definitions) have a component property. If this is not possible, you can implement a mock component that will be used as a component for wizard steps.

To use the component import it from the common package:

import Wizard from '@data-driven-forms/common/wizard';

And use your wizard component as Wizard prop:

const CustomWizard = (props) => { ... }
const WrappedWizard = (props) => <Wizard Wizard={CustomWizard} {...props} />

Custom wizard (and all other nested components) then can access the wizard api via WizardContext:

import WizardContext from '@data-driven-forms/react-form-renderer/wizard-context';
const CustomWizard = (props) => {
const {
crossroads,
formOptions,
currentStep,
handlePrev,
onKeyDown,
jumpToStep,
setPrevSteps,
handleNext,
navSchema,
activeStepIndex,
maxStepIndex,
isDynamic
} = useContext(WizardContext);
...
}

You can notice that this context also contains formOptions. It contains the same functions as the regular one, however, some of the functions are enhanced to support wizard functionality.

PropsTypeRequiredDefaultDescription
namestring,numbernoundefinedName of the step
nextStepobject/stepKey of next step/functionnoundefinedSee below
fieldsarrayyesundefinedAs usual
conditionalSubmitFlagstringno"@@ddf-common-wizard__conditional-submit-step"See below

A) string - no branching, name of the next step

{
nextStep: 'next-step-name'
}

B) object - simple branching

nextStep: {
when: 'source-type',
stepMapper: {
aws: 'aws-step',
google: 'google-step',
...
},
},

i.e.: When source-type is asw go to to the aws-step.

C) function - complex branching

another option is to use custom function. The custom function receives as the first argument an object with values and the function has to return a name in string.

nextStep: ({ values }) => (values.aws === '123' &&& values.password === 'secret') ? 'secretStep' : 'genericStep'

D) conditional submit step

Based on a form state value, a step can change into the last step in the wizard and show submit button instead of next button.

With default constant: @@ddf-common-wizard__conditional-submit-step

You can import this constant:

import { CONDITIONAL_SUBMIT_FLAG } from '@data-driven-forms/common/wizard';
...
// next step definition
nextStep: {
when: 'source-type',
stepMapper: {
aws: 'aws-step',
google: CONDITIONAL_SUBMIT_FLAG,
...
},
},

Or with custom constant value defined by conditionalSubmitFlag prop:

const schema = {
fields: [{
{
"component": "wizard",
"name": "wizard",
// custom flag definition
conditionalSubmitFlag: 'make-me-final-step',
fields: [{
name: 'step-1',
// next step definition
nextStep: {
when: 'value',
stepMapper: {
"value-one": 'step-2',
"value-two": 'make-me-final-step',
},
}
...
}, {
name: 'step-2'
...
}]
...
}}]
}

It is possible to set the initial state of the wizard component. This can be useful when an application returns users to a specific step.

{
component: 'wizard',
..., // fields, etc.
initialState: {
activeStep: 'second-step', // name of the active step
activeStepIndex: 1, // active index
maxStepIndex: 1, // max achieved index
prevSteps: ['first-step'], // array with names of previously visited steps
registeredFieldsHistory: { 'first-step': ['field'] }
// array of registered fields for each visited step
// only values from registered fields will be submitted
}
}

How to get the state from existing wizard? The state is passed to both onCancel and onSubmit:

A) onSubmit - (values, formApi, wizardState) => ... B) onCancel - (values, wizardState) => ...

Wizard share its configuration and props via WizardContext.

import WizardContext from '@data-driven-forms/react-form-renderer/wizard-context';
const {
crossroads, // variables changing the navigation
formOptions, // modified formOptions with submit and cancel handlers
currentStep, // curent step object
handlePrev, // going back in the wizard
onKeyDown, // overrides form onKeyDown event for the wizard
jumpToStep, // jump to step, jumpToStep(index, formOptions.valid)
setPrevSteps, // rewrites the nav schema, use to change the navigation
handleNext, // jumps to the nextStep: handleNext(nextStep)
navSchema, // internal object representing the schema of current wizard flow
activeStepIndex, // active index of the step
maxStepIndex, // maximal achieved step
isDynamic, // if form is dynamic (= it is branching steps)
prevSteps // array with names of previous steps
} = useContext(WizardContext);

This API is subject to change. If you implement custom components using these variables and functions, make sure that it is fully tested to prevent bugs when updating.

Following example shows only the basic custom implementation. To see other functionality as a dynamic navigation, check implementation in one of our mappers. (The PF4 wizard provides the most complex functionality.)