Wizard Forms
ForgeForm's Wizard Forms feature, introduced in v1.2.2, dramatically simplifies the creation of multi-step forms. Wizards guide users through complex processes by breaking them into sequential, validated steps.
warning
Important: Wizard Forms is still in beta. Some features might break or change as we continue to improve the functionality. Always test thoroughly before using in production.
Contents
When to Use Wizard Forms
Creating a Wizard with `createWizard`
Wizard Instance Methods and Properties
Comprehensive 3-Step Wizard Example
Wizard Forms with React Hook Form Resolver
When to Use Wizard Forms:
Wizard forms are ideal for scenarios like:
- Onboarding processes: Guiding new users through account setup, profile creation, and initial settings.
- Complex surveys or questionnaires: Breaking long surveys into logical sections for better user engagement and completion rates.
- E-commerce checkout flows: Stepping users through shipping address, billing information, payment details, and order confirmation.
- Configuration wizards: Setting up complex software or services with a step-by-step approach.
- Multi-stage applications: Collecting data across multiple related forms that need to be completed in a specific order.
Creating a Wizard with createWizard
The createWizard function is the starting point for building multi-step forms. It takes three main arguments:
steps: WizardStepConfig[](Required): An array defining each step of the wizard. Each step is aWizardStepConfigobject with:id: string: A unique identifier for the step. This id is crucial for programmatically controlling the wizard and referencing steps in lifecycle callbacks.schema: FormSchema<StepData>: A ForgeForm schema (created usingcreateSchema) that defines the data and validation rules for the step.<StepData>should be an interface or type representing the data structure for that specific step.
initialData?: Partial<T>(Optional): An object providing initial data for the wizard. This data will be pre-populated in the form fields and is useful for scenarios like editing existing data in a wizard format.<T>is the type that represents the combined data across all wizard steps.options?: WizardOptions<T>(Optional): An object to configure wizard behavior and lifecycle events. It accepts the following callback functions:-
onStepChange?: (stepId: string, index: number) => void: Called whenever the active step changes. Provides thestepIdand its index (0-based). Useful for updating UI elements like progress bars. -
onValidationSuccess?: (stepId: string, data: any) => void: Invoked after a step validates successfully whennextStepis called. Provides thestepIdand the validated data for that step. Useful for saving step data or triggering UI updates on successful validation. -
onValidationError?: (stepId: string, errors: FormErrors) => void: Called when validation fails for a step duringnextStep. Provides thestepIdand theerrorsobject. Useful for displaying step-specific error messages to the user. -
onComplete?: (finalData: any) => void: Triggered when the wizard is successfully completed (all steps validated andnextStepcalled on the last step). Provides the aggregatedfinalDatafrom all steps. This is where you would typically handle form submission to a server.
-
Wizard Instance Methods and Properties: Controlling Wizard Flow
Once you create a wizard instance using createWizard(), you gain access to several methods and properties to control its behavior:
-
wizard.nextStep(stepData?: object): Promise<boolean>: Moves the wizard to the next step.stepData(Optional): Data for the current step. If provided, it's merged into the wizard's overall data.- Returns a
Promise<boolean>: Resolves totrueif navigation is successful (current step validates),falseif validation fails.
-
wizard.nextStep(stepData?: object): Promise<boolean>: Moves the wizard to the next step.-
stepData(Optional): Data for the current step. If provided, it's merged into the wizard's overall data. -
Returns a
Promise<boolean>: Resolves totrueif navigation is successful (current step validates),falseif validation fails.
-
-
wizard.previousStep(): void: Moves the wizard to the preceding step. Has no effect if already at the first step. -
wizard.goToStep(stepId: string): void: Navigates the wizard directly to the step with the providedstepId. Useful for implementing step navigation menus or conditional branching in wizards. -
wizard.reset(): void: Resets the wizard to its initial state. Clears all collected data, sets the current step back to the first step, and resets validation history. Useful for allowing users to restart the wizard from the beginning. -
wizard.getProgress(): number: Returns the current progress of the wizard as a number between 0 and 1. Useful for displaying a progress bar or percentage indicator in the UI. Calculates progress based on the current step index and total steps. -
wizard.getState(): { currentStepId: string; currentStepIndex: number; data: Partial<T>; completedSteps: boolean[]; }: Returns an object containing the current state of the wizard, including:currentStepId,currentStepIndex,data, andcompletedSteps(an array of booleans indicating if each step has been completed and validated). Useful for persisting and restoring wizard state, or for advanced UI logic that depends on the wizard's internal state.
Properties:
wizard.currentStepIndex: number: Read-only property that provides the 0-based index of the current active step.wizard.currentStepId: string: Read-only property that returns theidof the current step.wizard.totalSteps: number: Read-only property indicating the total number of steps defined in the wizard.wizard.data: Partial<T>: Read-write property (though typically updated throughnextStepand other methods) that holds all the data collected across the wizard's steps. This object aggregates data from each step, keyed by the field names defined in your schemas.
Comprehensive 3-Step Wizard Example (Revisited)
Let's revisit and enhance the 3-step wizard example to demonstrate the methods and properties in a more complete context:
Wizard Forms with React Hook Form Resolver
ForgeForm Wizard Forms can be seamlessly integrated with React Hook Form using forgeFormResolver. This powerful combination allows you to leverage React Hook Form's excellent form state management and ForgeForm's robust schema-based validation within your multi-step wizards.
Example: 3-Step Wizard with React Hook Form Resolver
Let's create a 3-step wizard similar to the previous example, but now integrated with React Hook Form for form state and validation handling within each step:
-
Import necessary modules:
We import
useForm,useFormContext,FormProviderfromreact-hook-formand ForgeForm related functions. -
Define Step Schemas and Wizard: Schemas and the wizard are defined similarly to the previous Wizard example, but now schemas are specific to each step's data interface (e.g.,
Step1HookFormData). -
Step Components using
useFormContext: Each step component (Step1Component,Step2Component,Step3Component) usesuseFormContext<StepData>()to access React Hook Form'sregisterfunction anderrorsobject. This allows each step to manage its own input fields and display errors within the React Hook Form context. -
FormProvider: The mainWizardHookFormExamplecomponent wraps the entire form with<FormProvider {...formMethods}>. This makes the React Hook Form methods (register,handleSubmit,errors, etc.) available to all step components rendered within it, viauseFormContext. -
useFormInitialization withforgeFormResolver:We initialize React Hook Form's
useFormoutside the component's render to persist the form state across step changes. Crucially, we useforgeFormResolver(wizard.getCurrentStepSchema())to link the resolver to the current step's schema from the ForgeForm wizard.wizard.getCurrentStepSchema()is a helper method (you'd need to add this to yourcreateWizardimplementation, or track current schema manually) to get the schema for the active step. Initially, it's the schema of the first step. -
handleNextfunction:- Calls
clearErrors()to reset errors from previous steps. - Gets current step data using
formMethods.getValues(). - Calls
wizard.nextStep(stepData)to validate the step using ForgeForm Wizard and move to the next step. - If validation succeeds (
successistrue):formMethods.resetis called to clear errors and optionally keep the valid values for the next step's form (usingkeepValues: true).setCurrentStepIndexStateandsetProgressare updated.formMethods.rebuildModeis essential: it updates React Hook Form's resolver to use the schema of the new current step after a successfulnextStep.
- If validation fails (
successisfalse):wizard.validateCurrentStep()is called to get detailed validation errors from ForgeForm.setErrorfrom React Hook Form is used to manually set errors for each field based on the errors from ForgeForm, so React Hook Form can display them correctly.
- Calls
-
handlePreviousfunction:- Calls
wizard.previousStep()to move to the previous step. - Updates
setCurrentStepIndexStateandsetProgress. - Crucially, calls
formMethods.rebuildModeto update the resolver to the previous step's schema. clearErrors()is called to clear any errors as the user goes back.
- Calls
-
handleSubmitFinalfunction:- This is passed to React Hook Form's
handleSubmitfor the final step's submission. - Calls
wizard.nextStep(data)to perform final validation on the last step. - If final validation is successful, it alerts success, logs final data, resets the wizard and React Hook Form, and resets the resolver to the first step's schema for the next wizard usage.
- Otherwise, it alerts the user of validation errors.
- This is passed to React Hook Form's
-
Conditional Rendering of Step Components: The step components (
Step1Component,Step2Component,Step3Component) are conditionally rendered based onwizard.currentStepIndexto show the appropriate step UI. -
Rebuilding Resolver: The
rebuildModemethod inuseFormis key to dynamically updating the resolver as the wizard progresses through steps with different schemas. This ensures React Hook Form always validates against the correct schema for the active step.