While you’re free to use FormKit
inputs by themselves, you’ll usually want to group them into a form. To do this, simply wrap your inputs in a <FormKit type="form">
.
The form
type will actively collect all the values from child inputs, using the name
of each input as the property name in the resulting data object (just like groups). You can also read and write to form values using v-model just as you would on any input.
A <FormKit type="form">
tracks the form's validation state and prevents users from submitting the form if any inputs are invalid.
As a convenience, the form
outputs a submit button automatically, and provided themes also include a loading spinner. You can alter this button with the submit-label
and submit-attrs
props, or disable with :actions="false"
. You can pass any FormKit props to submit-attrs
. In the example below, we pass classes, data
attributes, help text, and even tell the included submit button to be un-ignored:
<FormKit
type="form"
submit-label="Update"
:submit-attrs="{
inputClass: 'my-input-class',
wrapperClass: 'my-wrapper-class',
'data-theme': `dark`,
help: 'My button help text',
ignore: false
}"
></FormKit>
Excluding backend functionality, here is a fully featured form with inputs (form
, text
, email
, password
), help text, labels, validation with custom messages, and error and submission handling:
You can populate an entire form by providing a value
prop to the <FormKit type="form">
. The value
prop should be an object of input name to input value pairs. You may also use v-model
to populate a form if you require two-way data binding:
Be sure to either v-model
a ref
or a property of a reactive
object. Do not v-model
the reactive object itself as it leads to unexpected behavior.
Forms are usually submitted through user actions like clicking a submit button or hitting the enter
key on a text node within the form. Upon submission, the form (in sequence):
@submit-raw
event.submitted
state to true on all inputs — displaying any remaining validation errors (regardless of the validation-visibility
).@submit-invalid
event is fired.@submit
event.@submit
handler returns a Promise
, sets the form’s state to loading
until it resolves.Using v-model
data in your submit handler can lead to unintended form mutations. FormKit automatically collects form data for you, so use the unbound copy of your form’s data that is passed to your submission handler instead.
The most common method of form submission in a modern SPA is an XHR request (think axios or fetch). FormKit is well suited to this task:
@submit
handler 1) the collected form data as a single request-ready object (no v-model
needed), and 2) the form
input's core node, as a convenience.loading
becomes true at context.state.loading
and a spinner is displayed on the genesis
theme).To submit a form via page request, simply leave off the @submit
handler. Just like native HTML, you can also provide an action
and optionally a method
attribute.
While submitting a form using any standard HTML method is valid (like clicking a submit
button, or hitting enter
on a text input) — you may also submit a form programmatically. There are 2 ways to do this:
this.$formkit.submit('form-id')
(submitForm('form-id')
for the composition API).$formkit.submit()
node.submit()
You can also submit a form programmatically by calling node.submit()
on the form’s (or any input inside the form) core node. To do this you need to retrieve an instance of the core node.
To disable all the inputs in a given form, including the submit button, you can use the disabled
prop.
When using an async @submit
handler, FormKit will automatically disable the form (and set the state to loading
) while the submit handler is pending.
You can reset your form (or any input) back to its initial state by calling $formkit.reset(formId)
.
When using the composition API, you can directly access the reset function by importing it from core: import { reset } from '@formkit/core'
.
It’s important to note that the "initial state" of a form is not necessarily an empty form. If you have a default :value
or v-model
on the form or on individual inputs in the form, FormKit automatically merges these together to produce your initial value, and will restore to this merged state on reset.
Optionally you can provide a second argument to reset(formId, initialState)
if you would prefer an alternative reset state.
Forms will not submit until all the inputs in the form are passing their validation rules.
In addition to not firing the submit event, a message is displayed above the submit button indicating the form is still incomplete. You can customize this message using the incomplete-message
prop or disable it by setting the prop to false
.
If you want to change the incomplete message across all forms on your project, you can modify the i18n locale message for ui.incomplete
.
When a user attempts to submit a form containing inputs that have failing validations, the @submit-invalid
event is fired.
For example, we could use this event to alert our users of the failing validation rules.
The validity of all inputs within a form is tracked automatically in the context object. This can be useful when creating various interfaces. For example, if you wanted a submit button to be disabled until all inputs are valid, you could use the state.valid
property to do so.
In the above example we extract the context object from the #default
slot, but there are other ways as well. The context object is available on each input’s core node on the node.context
property, and you can fetch an input’s node a number of ways.
With FormKit, adding front-end validation to your form is easy — but what about errors produced by your backend framework, or ones you want to manually assign? There are two types of errors you can assign to a form:
Form errors (ones that apply to the entire form) can be set three ways.
errors
prop on a <FormKit type="form">
.node.setErrors()
.$formkit.setErrors()
Vue plugin method.errors
propLike with any FormKit input, you can directly assign errors using the errors
prop. These errors are always visible (not subject to validation-visibility
).
node.setErrors()
Setting your form’s errors using node.setErrors
is convenient since your submit handler is passed the form’s node
object as its second argument. node.setErrors()
takes 2 arguments — an array for form errors, and a keyed object for input errors:
$formkit.setErrors()
Alternatively, you can set errors directly on a form by giving the form an id
and then calling $formkit.setErrors('id', ['Form error here'])
. The setErrors
method must be passed the id
of the form, and then can handle 1 or 2 additional arguments — the form errors, and the input errors:
By default errors that were set on inputs using setErrors()
are automatically cleared when a user changes the value of that input. You can change this default behavior by setting the preserve-errors
prop.
To clear all the errors on the form (regardless of the preserve-errors
prop) call node.clearErrors()
.
If you prefer to preserve errors by default, you can change the default behavior by modifying the preserveErrors
config option. This can be done globally or for a single form:
When using Vue 3’s composition API, you can access setErrors
and clearErrors
by importing them directly from @formkit/vue
.import { setErrors, clearErrors } from '@formkit/vue'
Input errors (ones to be displayed with specific inputs in a form) can be applied three ways:
errors
prop on each individual input.input-errors
prop on the form (also works with groups and lists).$formkit.setErrors()
Vue plugin method (see example above).errors
propThe most basic way to display errors on a form is using the errors
prop that is available on each FormKit
input.
input-errors
propYou can also conveniently set error messages for all inputs in your form (or group or list) using the input-errors
prop. The prop accepts an object of errors, where the keys are input names (relative node addresses are supported) and the value is an error or array of errors to apply to that input.
It can be helpful for accessibility to provide a summary of validation and error messages at the top of your form. FormKit provides a <FormKitSummary />
component to render this summary for you.
This component will automatically render all of a form’s validation and error messages with jump links to the inputs they apply to. These errors are only shown after submitting the form, but they are wrapped in an aria-live
region to ensure screen readers will be notified when the errors present themselves. Additionally, the page will automatically scroll to the summary box and focus on the first error listed.
<FormKitSummary />
is not a globally registered component — you must import it:
import { FormKitSummary } from '@formkit/vue'
The summary component should generally be nested in the form it is summarizing. If you would like to move the summary to a different location on the page, you can do so by providing the form’s core node as the node
prop.
By default, a form’s validation and error messages are placed directly above the form’s actions section. However, you can choose to render these anywhere on your page by using the <FormKitMessages />
component. <FormKitMessages />
is not a globally registered component — you must import it:
import { FormKitMessages } from '@formkit/vue'
There are two ways to use <FormKitMessages />
:
Place a <FormKitMessages />
component anywhere inside your form, and the form’s messages will automatically be moved to that location:
node
To move messages anywhere in the DOM — even outside the form — you can pass the form’s core node as a prop to <FormKitMessages />
. In this example, we use the messages to create a toast-style popup:
The <FormKitMessages />
component has a few additional configuration options:
Prop | Default | Description |
---|---|---|
node | inherited | The core node to render messages for. By default this is inherited from the node’s parent (if it exists). |
sectionsSchema | {} | Override the internal messages and message sections (same default structure as other input’s messages section). |
defaultPosition | false | By default, FormKitMessages moves the rendered messages to a new location. If you would like to render the messages in both locations, set this prop to true . |
When an input is unmounted from a form — for example when using v-if
— its key and value are removed from the form’s data. However, in some circumstances it may be preferable to keep the key/value pair even after the input has been removed. This can be accomplished by using the preserve
prop:
FormKit provides a few composables to help you access the form’s data and context. These are available to be imported from the @formkit/vue
package:
The useFormKitContext
is a composable that returns the form’s context object as a vue Ref
whenever it becomes available. This must be used in a component that is a child of a <FormKit>
component (like the form). The first argument is an optional traversal path that allows you to navigate to any node within your form tree. The second argument is an optional effect callback that will be invoked whenever the context becomes available.
Similar to useFormKitContext
this composable finds any <FormKit>
context object if that component has been given an explicit id
. Optionally you can provide an effect callback that will be invoked whenever the node becomes available.
Fetches any FormKit node that has an explicit id
. It returns a Ref
that will populate with the core node whenever it is mounted. Optionally you can provide an effect callback that will be invoked whenever the node becomes available.
The node itself is not reactive and should be used for imperative actions like node.submit()
. The context object is reactive and should be used for reading and reacting to the form’s state.
In order to prevent password managers such as 1Password and LastPass from autofilling your email and password input fields, set the respective props data-1p-ignore
and data-lpignore
to true
on the inputs themselves. If you would like for this to be done automatically, check out the adds attributes to prevent autofill plugin.
Forms are technically considered input
types — so they share many of the universal props that standard inputs use.
Prop | Type | Default | Description |
---|---|---|---|
disabled | Boolean | false | Disables the form submit button and all the inputs in the form. |
incomplete-message | String/Boolean | {locale}.ui.incomplete | The message that is shown to near the submit button when a user attempts to submit a form, but not all inputs are valid. |
submit-attrs | Object | {} | Attributes or props that should be passed to the built-in submit button. |
submit-behavior | String | disabled | Async submit handlers automatically disable the form while pending, you can change this by setting this prop to 'live'. |
submit-label | String | Submit | The label to use on the built-in submit button. |
actions | Boolean | true | Whether or not to include the actions bar at the bottom of the form (ex. you want to remove the submit button and use your own, set this to false ). |
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 |
---|---|
form | Responsible for rendering the form tag and listening to submit events. |
actions | Responsible for a container at the bottom of the form with form actions like the submit button. |
submit | Responsible for a submit button — by default a FormKit input type submit . |
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. |
All FormKit inputs are designed with the following accessibility considerations in mind. Help us continually improve accessibility for all by filing accessibility issues here: