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.
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
multi-step
input type in action: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 childrenstep
: 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.
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.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
.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
.
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:
valid-step-icon
on the multi-step
input to change the icon for all steps inside the input.valid-step-icon
on a step
input to change or override the icon just for that step.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.
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.
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.
Prop | Type | Default | Description |
---|---|---|---|
allowIncomplete | boolean | true | When true , allows users to navigate between steps even if current step is invalid. |
tabStyle | string | tab | Used to set a data-attribute for creating tab styles. Default theme ships with support for tab and progress tab styles. |
hideProgressLabels | boolean | false | When true, hides labels for the progress tab style. |
validStepIcon | string | check | Specifies 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. |
beforeStepChange | function | undefined | A 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 | |||
config | Object | {} | Configuration options to provide to the input’s node and any descendent node of this input. |
delay | Number | 20 | Number of milliseconds to debounce an input’s value before the commit hook is dispatched. |
dirtyBehavior | string | touched | Determines how the "dirty" flag of this input is set. Can be set to touched or compare — touched (the default) is more performant, but will not detect when the form is once again matching its initial state. |
errors | Array | [] | Array of strings to show as error messages on this field. |
help | String | '' | Text for help text associated with the input. |
id | String | input_{n} | The unique id of the input. Providing an id also allows the input’s node to be globally accessed. |
ignore | Boolean | false | Prevents an input from being included in any parent (group, list, form etc). Useful when using inputs for UI instead of actual values. |
index | Number | undefined | Allows 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. |
label | String | '' | Text for the label element associated with the input. |
name | String | input_{n} | The name of the input as identified in the data object. This should be unique within a group of fields. |
parent | FormKitNode | contextual | By default the parent is a wrapping group, list or form — but this props allows explicit assignment of the parent node. |
prefix-icon | String | '' | Specifies an icon to put in the prefixIcon section. |
preserve | boolean | false | Preserves the value of the input on a parent group, list, or form when the input unmounts. |
preserve-errors | boolean | false | By 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-schema | Object | {} | An object of section keys and schema partial values, where each schema partial is applied to the respective section. |
suffix-icon | String | '' | Specifies an icon to put in the suffixIcon section. |
type | String | text | The type of input to render from the library. |
validation | String, Array | [] | The validation rules to be applied to the input. |
validation-visibility | String | blur | Determines when to show an input's failing validation rules. Valid values are blur , dirty , and live . |
validation-label | String | {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-rules | Object | {} | Additional custom validation rules to make available to the validation prop. |
value | Any | undefined | Seeds the initial value of an input and/or its children. Not reactive. Can seed entire groups (forms) and lists.. |
Prop | Type | Default | Description |
---|---|---|---|
label | string | Used to change the tab label of the step. If not custom label is supplied the step's name will be used. | |
previousLabel | string | Previous | Used to change the label of the default previousAction button. |
nextLabel | string | Next | Used to change the label of the default nextAction button. |
previousAttrs | object | [object Object] | Used to apply attributes to the default previousAction button input. |
nextAttrs | object | [object Object] | Used to apply attributes to the default nextAction button input. |
validStepIcon | string | check | Specifies 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 . |
beforeStepChange | function | undefined | A 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 | |||
config | Object | {} | Configuration options to provide to the input’s node and any descendent node of this input. |
delay | Number | 20 | Number of milliseconds to debounce an input’s value before the commit hook is dispatched. |
dirtyBehavior | string | touched | Determines how the "dirty" flag of this input is set. Can be set to touched or compare — touched (the default) is more performant, but will not detect when the form is once again matching its initial state. |
errors | Array | [] | Array of strings to show as error messages on this field. |
help | String | '' | Text for help text associated with the input. |
id | String | input_{n} | The unique id of the input. Providing an id also allows the input’s node to be globally accessed. |
ignore | Boolean | false | Prevents an input from being included in any parent (group, list, form etc). Useful when using inputs for UI instead of actual values. |
index | Number | undefined | Allows 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. |
label | String | '' | Text for the label element associated with the input. |
name | String | input_{n} | The name of the input as identified in the data object. This should be unique within a group of fields. |
parent | FormKitNode | contextual | By default the parent is a wrapping group, list or form — but this props allows explicit assignment of the parent node. |
prefix-icon | String | '' | Specifies an icon to put in the prefixIcon section. |
preserve | boolean | false | Preserves the value of the input on a parent group, list, or form when the input unmounts. |
preserve-errors | boolean | false | By 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-schema | Object | {} | An object of section keys and schema partial values, where each schema partial is applied to the respective section. |
suffix-icon | String | '' | Specifies an icon to put in the suffixIcon section. |
type | String | text | The type of input to render from the library. |
validation | String, Array | [] | The validation rules to be applied to the input. |
validation-visibility | String | blur | Determines when to show an input's failing validation rules. Valid values are blur , dirty , and live . |
validation-label | String | {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-rules | Object | {} | Additional custom validation rules to make available to the validation prop. |
value | Any | undefined | Seeds the initial value of an input and/or its children. Not reactive. Can seed entire groups (forms) and lists.. |
Section-key | Description |
---|---|
tabs | A wrapper around all of the tabs. |
tab | A button element that contains the tab name and the decorator to reflect validation state. |
tabLabel | A span element that contains the name of the tab. |
badge | A span element used as a decorator for showing current tab validity state. |
steps | A wrapper around all steps. |
step | A 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. |
stepInner | A wrapper around the default slot content for a step. |
stepActions | A wrapper around the action buttons for moving between steps. |
stepPrevious | A wrapper around the action button for navigating to the previous step. |
stepNext | A wrapper around the action button for navigating to the next step. |
Show Universal section keys | |
outer | The outermost wrapping element. |
wrapper | A wrapper around the label and input. |
label | The label of the input. |
prefix | Has no output by default, but allows content directly before an input element. |
prefixIcon | An element for outputting an icon before the prefix section. |
inner | A wrapper around the actual input element. |
suffix | Has no output by default, but allows content directly after an input element. |
suffixIcon | An element for outputting an icon after the suffix section. |
input | The input element itself. |
help | The element containing help text. |
messages | A wrapper around all the messages. |
message | The element (or many elements) containing a message — most often validation and error messages. |