Docs Navigation


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.

Provided submit button

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".

Full example form

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:

Load Live Example


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.

Load Live Example
v-model and reactive objects
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.
Submitted data & v-model
Using v-model data in your submit handler could lead to unintended form mutations. Instead, use the unbound copy of your form’s data that is passed to your submission handler.


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):

  1. Ensures all inputs are settled (finished debouncing).
  2. Emits the @submit-raw event.
  3. Sets the submitted state to true on all inputs — displaying any remaining validation errors (regardless of the validation-visibility).
  4. If all inputs are valid it fires the @submit event.
  5. If the @submit event returns a Promise sets the form’s state to loading until it resolves.

Submitting via XHR/Fetch request

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:

  • It hands your submit handler a request-ready object.
  • If you use an async submit handler, it will disable your form’s inputs and apply a loading state to your form (loading becomes true at context.state.loading and a spinner is displayed on the genesis theme).
  • It handles backend errors by placing error messages directly on the failing inputs.
Load Live Example

Submitting as a page request

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.

Load Live Example

Submitting forms programmatically

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:

  • Using this.$formkit.submit('form-id') (submitForm('form-id') for the composition api).
  • Using a core node object.

Submitting with $formkit.submit()

Load Live Example

Submitting with 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.

Load Live Example


Forms will not submit until all the inputs in the form are passing their validation rules.

Validation incomplete message

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.

Load Live Example
Global customization
If you want to change the incomplete message across all forms on your project, you can modify the i18n locale message for ui.incomplete.

Validity state

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.

Load Live Example
Getting the context object
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.


To disable all the inputs in a given form, including the submit button, you can use the disabled prop.

Load Live Example
Disabled automatically
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 it’s initial state by calling $formkit.reset(formId).

Load Live Example
Composition API
When using the composition api you can directly access the reset function by importing it from core: import { reset } from '@formkit/core'.

Initial values

It’s important to note that the "initial state" of a form is not necessarily an empty form. You can have a default :value or v-model on the form and 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.

Error handling

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. These are displayed at the bottom of the form above the submit button. An example would be a global message like "Sorry, our server isn’t working right now”.
  • Input errors. Errors to be placed on specific inputs within your form, typically these are validation errors from your backend, like "Sorry this username is already taken".

Form errors

Form errors (ones that apply to the entire form) can be set three ways.

  • Using the errors prop on a <FormKit type="form">.
  • Using a core node node.setErrors().
  • Using the $formkit.setErrors() Vue plugin method.

Using the errors prop

Like with any FormKit input, you can directly assign errors using the errors prop. These errors are always visible (not subject to validation-visibility).

Load Live Example

Using 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:

Load Live Example

Using $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:

Load Live Example

Clearing 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().

Load Live Example

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:

Load Live Example
Composition API
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

Input errors (ones to be displayed with specific inputs in a form) can be applied three ways:

  • Manually using the errors prop on each individual input.
  • Using the input-errors prop on the form (also works with groups and lists).
  • Using the $formkit.setErrors() Vue plugin method (see example above).

Manually using errors prop

The most basic way to display errors on a form is using the errors prop that is available on each FormKit input.

Load Live Example

Using input-errors prop

You 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.

Load Live Example

Unmounting inputs

When inputs are unmounted from a form — for example when using v-if — the key and value is 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.

Load Live Example


Forms are technically considered input types — so they share many of the universal props that standard inputs use.

Prop Type Default Description
disabledBooleanfalseDisables the form submit button and all the inputs in the form.
incomplete-messageString/Boolean{locale}.ui.incompleteThe message that is shown to near the submit button when a user attempts to submit a form, but not all inputs are valid.
submit-attrsObject{}Attributes or props that should be passed to the built-in submit button.
submit-behaviorStringdisabledAsync submit handlers automatically disable the form while pending, you can change this by setting this prop to 'live'.
submit-labelStringSubmitThe label to use on the built-in submit button.
actionsBooleantrueWhether 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
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.
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.
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.
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.

Section keys

Section-key Description
formResponsible for rendering the form tag and listening to submit events.
actionsResponsible for a container at the bottom of the form with form actions like the submit button.
submitResponsible for a submit button — by default a FormKit input type submit.
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.
innerA wrapper around the actual input element.
suffixHas no output by default, but allows content directly after an input element.
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.