Multi-Step Input Plugin

Introduction

FormKit ships with a first-party multi-step input plugin available from the @formkit/addons package. This input allows you to build a wizard or easily break your forms into multiple steps. Breaking forms into multiple steps can improve the user-experience of larger forms by keeping them feeling small and approachable compared to listing all inputs at once.

Multi-step Component Overview

2 mins

Installation

To get started, import createMultiStepPlugin from @formkit/addons along with the accompanying styles. The styles are completely standalone and have no dependency on the genesis theme that ships with FormKit. This means that if you are using Tailwind to style your inputs, your input styles will still display as expected when wrapped in the multi-step input type.

// formkit.config.js
import { defaultConfig } from '@formkit/vue'
import { createMultiStepPlugin } from '@formkit/addons'
import '@formkit/addons/css/multistep'

const config = defaultConfig({
  plugins: [createMultiStepPlugin()],
})

export default config

A quick demonstration of the multi-step input type in action:

Load live example

Usage

The createMultiStepPlugin function registers two new input types for you to use with the FormKit component.

  • multi-step: The wrapping group for the entire multi-step input. This input keeps track of which step is active, validation and errors per step, and should only contain step inputs as its immediate children
  • step: The wrapping group for a given step within your multi-step input. Should only be an immediate child of a multi-step input. Its children will be rendered as the contents of the step.

Using these inputs together is as simple as wrapping any markup you want to have present within a step in a multi-step form.

<FormKit type="multi-step">
  <FormKit type="step" name="stepOne">
    <!-- content for stepOne goes here! -->
  </FormKit>
</FormKit>

Out-of-the-box the parent multi-step input will track the validity of the inputs contained in each child step input and prevent advancing to the next step until the current step is valid. The count of total blocking validations and errors will be shown next to the current step name if a user attempts to advance to the next step or submit the form before satisfying the current step's input validations.

Tab style

The multi-step input ships with two available tab styles.

  • tab: The default tab experience. Each step name is show in a tab with an active state. Error count is shown in the top right of the tab.
  • progress: A progress bar style where each step is a "node" on a timeline of total steps. With this display mode you can also use the hide-progress-labels prop to hide the step names.
Load live example

Step labels

By default the multi-step input will use the name attribute of its child step inputs to generate labels for steps. If you'd like more control over the display of your step names you can use the label prop. You can also customize the labels that appear in the stepActions section of your step using the previous-label and next-label props.

  • label: An override for the step name that should appear in the multi-step tabs.
  • previous-label: an override for the stepPrevious button label which defaults to Back.
  • next-label: an override for the stepNext button label which defaults to Next.
Load live example

Allow incomplete steps

By default the multi-step input will allow advancing to later steps even if the current step or a step between the current step and the target step has blocking validation messages. To prevent a user from jumping ahead set the allow-incomplete prop to false.

Load live example

Valid step icon

When a step has been completed with no validation errors the multi-step input will — by default — render a check icon showing that the step is valid and no more action is required. The valid-step-icon is a FormKit Icon and can be changed via a prop like any other FormKit icon.

You can either:

  • Change the valid-step-icon on the multi-step input to change the icon for all steps inside the input.
  • Change the valid-step-icon on a step input to change or override the icon just for that step.
Load live example

Customizing step actions

Each step in a multi-step input has default buttons rendered for moving between steps. By default the first step in a multi-step will only have a stepNext action button rendered, and the last step will only have a stepPrevious action button. This allows a multi-step to act as a self-contained group within the context of a larger form.

If you want to add a custom action such as a form submit to a multi-step — useful if you're using the multi-step as your whole form — you can do so by overriding the stepNext slot on the desired step. In this case we'll add a submit input to the last step in our multi-step input to submit the form.

The stepNext and stepPrevious sections have access to the incrementStep handler — which returns a callable function — to enable programatic navigation.

Tab navigation

By default, the stepNext in a multi-step input uses event listeners to capture tab navigation via keyboard and allow users to cycle through all available steps within a multi-step.

If you want to preserve this behaviour in your own custom stepNext implementation then be sure to add a data-next="true" attribute to your focusable element that triggers step navigation.

Load live example

The beforeStepChange event

Sometimes you need to do something with your form data between steps. Maybe you want to submit each step independently to your back-end or you need to log analytics events to determine how far users are making it through your form. In cases such as these you can use the beforeStepChange event. beforeStepChange accepts a function and is provided a context object with the following keys:

  • currentStep: The currently active step node context object that the user is navigating away from.
  • targetStep: The step node context object that the user is navigating to.
  • delta: The distance between steps. Positive integers represent stepping forward, negative integers represent stepping backward.

Your beforeStepChange function should return a Boolean. Returning false will prevent the step change from ocurring.

beforeStepChange can be used on your multi-step input in which case it will apply to all steps. Additionally you can use beforeStepChange on a specific step input to run your function only when navigating away from the step which has the function assigned. beforeStepChange applied to a step will override any beforeStepChange set on a parent multi-step if one exists.

Load live example

Props & Attributes (multi-step)

PropTypeDefaultDescription
allowIncompletebooleantrueWhen true, allows users to navigate between steps even if current step is invalid.
tabStylestringtabUsed to set a data-attribute for creating tab styles. Default theme ships with support for tab and progress tab styles.
hideProgressLabelsbooleanfalseWhen true, hides labels for the progress tab style.
validStepIconstringcheckSpecifies an icon to put in the badge section when a step is valid. When applied to the multi-step the icon will be applied to all child step inputs.
beforeStepChangefunctionundefinedA function to run before the active step is changed. The function is supplied with a context object containing currentStep and targetStep which are both FormKit node context objects. Additionally, delta is supplied as an integer which reflects the distance between currentStep and targetStep. When supplied to the multi-step this function will fire on every step change.
Show Universal props
configObject{}Configuration options to provide to the input’s node and any descendent node of this input.
delayNumber20Number of milliseconds to debounce an input’s value before the commit hook is dispatched.
dirtyBehaviorstringtouchedDetermines how the "dirty" flag of this input is set. Can be set to touched or comparetouched (the default) is more performant, but will not detect when the form is once again matching its initial state.
errorsArray[]Array of strings to show as error messages on this field.
helpString''Text for help text associated with the input.
idStringinput_{n}The unique id of the input. Providing an id also allows the input’s node to be globally accessed.
ignoreBooleanfalsePrevents an input from being included in any parent (group, list, form etc). Useful when using inputs for UI instead of actual values.
indexNumberundefinedAllows an input to be inserted at the given index if the parent is a list. If the input’s value is undefined, it inherits the value from that index position. If it has a value it inserts it into the lists’s values at the given index.
labelString''Text for the label element associated with the input.
nameStringinput_{n}The name of the input as identified in the data object. This should be unique within a group of fields.
parentFormKitNodecontextualBy default the parent is a wrapping group, list or form — but this props allows explicit assignment of the parent node.
prefix-iconString''Specifies an icon to put in the prefixIcon section.
preservebooleanfalsePreserves the value of the input on a parent group, list, or form when the input unmounts.
preserve-errorsbooleanfalseBy default errors set on inputs using setErrors are automatically cleared on input, setting this prop to true maintains the error until it is explicitly cleared.
sections-schemaObject{}An object of section keys and schema partial values, where each schema partial is applied to the respective section.
suffix-iconString''Specifies an icon to put in the suffixIcon section.
typeStringtextThe type of input to render from the library.
validationString, Array[]The validation rules to be applied to the input.
validation-visibilityStringblurDetermines when to show an input's failing validation rules. Valid values are blur, dirty, and live.
validation-labelString{label prop}Determines what label to use in validation error messages, by default it uses the label prop if available, otherwise it uses the name prop.
validation-rulesObject{}Additional custom validation rules to make available to the validation prop.
valueAnyundefinedSeeds the initial value of an input and/or its children. Not reactive. Can seed entire groups (forms) and lists..

Props & Attributes (step)

PropTypeDefaultDescription
labelstringUsed to change the tab label of the step. If not custom label is supplied the step's name will be used.
previousLabelstringPreviousUsed to change the label of the default previousAction button.
nextLabelstringNextUsed to change the label of the default nextAction button.
previousAttrsobject[object Object]Used to apply attributes to the default previousAction button input.
nextAttrsobject[object Object]Used to apply attributes to the default nextAction button input.
validStepIconstringcheckSpecifies an icon to put in the badge section when the step is valid. When applied to a step the icon will be applied only to the target step.
beforeStepChangefunctionundefinedA function to run before the active step is changed. The function is supplied with a context object containing currentStep and targetStep which are both FormKit node context objects. Additionally, delta is supplied as an integer which reflects the distance between currentStep and targetStep. When supplied to a step this function will fire only when navigating away from the specified step.
Show Universal props
configObject{}Configuration options to provide to the input’s node and any descendent node of this input.
delayNumber20Number of milliseconds to debounce an input’s value before the commit hook is dispatched.
dirtyBehaviorstringtouchedDetermines how the "dirty" flag of this input is set. Can be set to touched or comparetouched (the default) is more performant, but will not detect when the form is once again matching its initial state.
errorsArray[]Array of strings to show as error messages on this field.
helpString''Text for help text associated with the input.
idStringinput_{n}The unique id of the input. Providing an id also allows the input’s node to be globally accessed.
ignoreBooleanfalsePrevents an input from being included in any parent (group, list, form etc). Useful when using inputs for UI instead of actual values.
indexNumberundefinedAllows an input to be inserted at the given index if the parent is a list. If the input’s value is undefined, it inherits the value from that index position. If it has a value it inserts it into the lists’s values at the given index.
labelString''Text for the label element associated with the input.
nameStringinput_{n}The name of the input as identified in the data object. This should be unique within a group of fields.
parentFormKitNodecontextualBy default the parent is a wrapping group, list or form — but this props allows explicit assignment of the parent node.
prefix-iconString''Specifies an icon to put in the prefixIcon section.
preservebooleanfalsePreserves the value of the input on a parent group, list, or form when the input unmounts.
preserve-errorsbooleanfalseBy default errors set on inputs using setErrors are automatically cleared on input, setting this prop to true maintains the error until it is explicitly cleared.
sections-schemaObject{}An object of section keys and schema partial values, where each schema partial is applied to the respective section.
suffix-iconString''Specifies an icon to put in the suffixIcon section.
typeStringtextThe type of input to render from the library.
validationString, Array[]The validation rules to be applied to the input.
validation-visibilityStringblurDetermines when to show an input's failing validation rules. Valid values are blur, dirty, and live.
validation-labelString{label prop}Determines what label to use in validation error messages, by default it uses the label prop if available, otherwise it uses the name prop.
validation-rulesObject{}Additional custom validation rules to make available to the validation prop.
valueAnyundefinedSeeds the initial value of an input and/or its children. Not reactive. Can seed entire groups (forms) and lists..

Sections

Step Name
⚠️
... Step content ...
Back
Next
Section-keyDescription
tabsA wrapper around all of the tabs.
tabA button element that contains the tab name and the decorator to reflect validation state.
tabLabelA span element that contains the name of the tab.
badgeA span element used as a decorator for showing current tab validity state.
stepsA wrapper around all steps.
stepA wrapper around step content from the default slot and the step’s action buttons. Each step has visibility styling automatically applied depending on if it is the current active step.
stepInnerA wrapper around the default slot content for a step.
stepActionsA wrapper around the action buttons for moving between steps.
stepPreviousA wrapper around the action button for navigating to the previous step.
stepNextA wrapper around the action button for navigating to the next step.
Show Universal section keys
outerThe outermost wrapping element.
wrapperA wrapper around the label and input.
labelThe label of the input.
prefixHas no output by default, but allows content directly before an input element.
prefixIconAn element for outputting an icon before the prefix section.
innerA wrapper around the actual input element.
suffixHas no output by default, but allows content directly after an input element.
suffixIconAn element for outputting an icon after the suffix section.
inputThe input element itself.
helpThe element containing help text.
messagesA wrapper around all the messages.
messageThe element (or many elements) containing a message — most often validation and error messages.