FormKit makes front end validation simple by letting you declare your validation rules directly on your inputs. It's easy to write custom rules too, but you'll rarely need to with 20+ production-ready rules.
Declaring which validation rules apply to a given input is as simple as providing a validation
prop. Rules can be declared using two syntaxes:
Validation rules can be declared by specifying each desired rule name separated by pipes |
. Some rules may also accept arguments, which can be supplied after a colon :
. You can use multiple arguments by comma separating them:
Validation rules can also be declared by providing an array. Each element of the array must be itself an array where the first element is the string name of the validation rule, and the remaining n
elements are arguments for that rule.
This is especially helpful if the arguments being provided need to be actual JavaScript types — for example, a regular expression (regex):
Validation rules are always computed in realtime — meaning a given field will always be either valid or invalid (it is considered invalid while pending async validation rules run). However — the visibility of the validation errors is determined by the validation-visibility
prop.
Visibility | Description |
---|---|
blur | (Default) Errors are shown after a user removes focus from an input. |
live | Errors are always visible. |
dirty | Errors are shown after a user modifies the value of an input. |
submit | Errors are shown only after a user attempts to submit a form. |
If an input is inside a form, then any remaining validation messages will be displayed to the end user when a user attempts to submit the form.
Due to FormKit's config inheritance, you can set validation-visibility
at a form
, group
, or list
level by using the config
prop, which you can still override on an input-by-input basis:
Validation rules operate according to a few default features, which you can change on a case-by-case basis with "rule hints":
required|length:5
then the length
rule will not run until the required
rule is passing.required
rule is the only exception).The above features can be modified when declaring your rules by using "hinting". Rule hints are small modifier characters you append to the beginning of a rule declaration to change its default behavior:
Hint | Name | Description |
---|---|---|
(200) | Debounce | Debounces the validation rule by the given number of milliseconds. |
+ | Empty | Runs the validation rule even if the input is empty (but not force the rule). |
* | Force | Runs the validation rule even if a previous rule was failing. |
? | Optional | Makes a validation rule optional (it is non-blocking meaning the form can still submit). |
(milli)
At times it makes sense to debounce your validation rules. To do this use the debounce hint — a parenthesis containing a duration in milliseconds — before your rule:
+
Sometimes you want a validation rule to run even when an input is empty. You can use the empty +
hint to do so:
*
The force hint ensures a validation rule will run even if a rule that is defined before it is failing (note: this does not mean it will run when an input is empty). Notice how this example will display both the length
and email
messages:
?
The optional hint allows a failing validation rule to not prevent form submission. In this example, notice how the form will not submit if the required
or confirm
rules are failing, but it will submit if the optional-hinted length
rule is failing:
You can use rule hints together. To do so, just place multiple hints before the rule declaration: required|*+(200)min:10
.
FormKit ships with over 35 production-ready validation rules, covering most validation needs. If you don't find one that meets your exact requirement, you can add a custom rule to suit your needs.
The value must be yes
, on
, 1
or true
. Useful for checkbox inputs — often where you need to validate if someone has accepted terms.
Checks if a value is only alphabetical characters. There are two character sets: latin and default. Latin characters are strictly [a-zA-Z]
, while the default set includes most accented characters, such as ä
, ù
, or ś
.
Checks if a value is only made of alphabetical characters or numeric digits. For the alphabetical portion you can pass default
or latin
- see alpha) above.
Checks if a value is only made of alphabetical characters or spaces. For the alphabetical portion you can pass default
or latin
- see alpha) above.
Checks if a number is (inclusively) between two other numbers. The input value must be a number, or the validation rule will fail.
Checks if the value of one input matches the value of another input — often used for password confirmations. There are two ways to specify which input to match:
_confirm
to the name
attribute of the second input.name
of the first input as an argument to the confirm rule in the second input confirm:name_of_input_1
(more specific).Note: the two inputs must be in the same group
or form
.
Checks if a value contains alphabetical characters. There are two character sets: latin and default. Latin characters are strictly [a-zA-Z]
, while the default set includes most accented characters, such as ä
, ù
, or ś
.
Checks if a value contains either alphabetical characters or numeric digits. For the alphabetical portion you can pass default
or latin
- see contains alpha) above.
Checks if a value contains alphabetical characters or spaces. For the alphabetical portion you can pass default
or latin
- see contains alpha) above.
Checks if a value contains a lowercase character. There are two character sets: latin and default. Latin characters are strictly [a-zA-Z]
, while the default set includes most accented characters, such as ä
, ù
, or ś
.
Checks if a value contains a number.
Checks if a value contains a symbol.
Checks if a value contains a uppercase character. There are two character sets: latin and default. Latin characters are strictly [a-zA-Z]
, while the default set includes most accented characters, such as ä
, ù
, or ś
.
Determines if a date is after the current date or a date supplied as the rule's argument. Dates used can either be JavaScript Date
objects or strings that can be parsed by Date.parse()
.
Determines if a date is before the current date or a date supplied as the rule's argument. Dates used can either be JavaScript Date
objects or strings that can be parsed by Date.parse()
.
Determines if a date is between (and including) the two dates supplied as the rule's arguments. Dates used can either be JavaScript Date
objects or strings that can be parsed by Date.parse()
.
Determines if a date is before or equal to the current date or a date supplied as the rule's argument. Dates used can either be JavaScript Date
objects or strings that can be parsed by Date.parse()
.
Determines if a date is after or equal to the current date or a date supplied as the rule's argument. Dates used can either be JavaScript Date
objects or strings that can be parsed by Date.parse()
.
Determines if a date is before the date in another node specified by its address. The address is provided as an argument to the rule. Dates used can either be JavaScript Date
objects or strings that can be parsed by Date.parse()
.
Determines if a date is after the date in another node specified by its address. The address is provided as an argument to the rule. Dates used can either be JavaScript Date
objects or strings that can be parsed by Date.parse()
.
Ensures the format of an input's date matches a specific date format. The format should be specified using the following formatting tokens:
Token | Valid values |
---|---|
MM | Two-digit month representation (01-12) |
M | Single-digit month representation (1-12) leading zero allowed |
DD | Two-digit day of the month (01-31) |
D | Single-digit day of the month (1-31), leading zero allowed |
YY | Two-digit year |
YYYY | Four-digit year |
Native date inputs always output the same format YYYY-MM-DD ...
even though they display dates according to the browser's locale. Using this rule to specify a different format would result in an input that can never be valid.
Checks if the input contains a valid email address.
Checks if the input's value ends with a given substring.
Checks that the input's value matches at least one of the provided arguments.
Checks that the input's value is over a given length, or between two length values. It works to validate arrays (like lists), objects (like groups), or string lengths. Can be used to simulate the native maxlength
and minlength
as well.
Checks if a value consists of only lowercase characters. There are two character sets: latin and default. Latin characters are strictly [a-zA-Z]
, while the default set includes most accented characters, such as ä
, ù
, or ś
.
Checks if the input matches a particular value or pattern. If you pass multiple arguments, it checks each until a match is found.
Instead of passing in strings within the validation prop for simple matching, you can template your argument with slashes /
to pass in your own regular expression.
When using the string String Syntax you cannot escape characters used to define the validation rules themselves (|,:)
. To use these characters in your regular expressions you must use the alternative Array Syntax.
Checks that a Number
is less than or equal to a maximum value. The maximum value defaults to 10
.
You can also use this rule to validate that the length of an Array
is less than or equal to a maximum value.
Checks that a Number
is greater than or equal to a minimum value. The minimum value defaults to 1
.
You can also use this rule to validate that the length of an Array
is more than or equal to a minimum value.
Checks to ensure the input data does not match a set of predefined values.
Checks if the input is a valid number as evaluated by isNaN()
.
Checks if the input is empty.
If you don't want whitespace to cause the required
rule to pass, you can pass trim
as an argument to the rule:
Checks multiple inputs and passes if any of them have a value.
Note: the two inputs must be in the same group
or form
.
Checks if the input starts with one of the provided options.
Checks if a value consists of only symbols.
Checks if a value consists of only uppercase characters. There are two character sets: latin and default. Latin characters are strictly [a-zA-Z]
, while the default set includes most accented characters, such as ä
, ù
, or ś
.
Checks if the input value appears to be a properly formatted URL including the protocol. This does not check if the URL actually resolves.
Validation rules are functions that accept a core node and return a boolean value — true
for passing and false
for failing. Additionally, any arguments passed to the validation rule are available as arguments 1-n
. Writing your own is straight forward — for example:
/**
* File: my-custom-rules/monday.js
*
* A contrived validation rule that ensures the input’s value is monday or mon.
*/
const monday = function (node) {
return node.value === 'monday' || node.value === 'mon'
}
export default monday
As mentioned in the validation rule hints section, validation rules — including your custom rules — operate according to default behaviors: they run in sequence, are skipped when the input's value is empty, are synchronous, and are blocking. If you want your rule's defaults to operate differently, you can override these on your custom validation rule:
/**
* A contrived validation rule that ensures the input’s value is monday or mon.
*/
const monday = function (node) {
return node.value === 'monday' || node.value === 'mon'
}
// override default rule behaviors for your custom rule
monday.blocking = false
monday.skipEmpty = false
monday.debounce = 20 // milliseconds
monday.force = true
export default monday
You can also override these behaviors on a case-by-case basis with rule hints.
Once you have a validation function written — you need to register the validation rule with FormKit — either globally or specifically on an input.
Validation rules can depend on values from other inputs in your form’s tree. To do so, use node traversal to locate another node and access its value:
Validation rules should always be pure functions. Use only the arguments passed in and do not perform any side effects.
To use a validation rule anywhere in your project, you can specify it wherever your FormKit plugin is registered with Vue.
import { createApp } from 'vue'
import App from './App.vue'
import { plugin, defaultConfig } from '@formkit/vue'
import monday from './my-custom-rules/monday'
// prettier-ignore
createApp(App).use(plugin, defaultConfig({
rules: { monday },
})).mount('#app')
Once installed you can use your validation rule in anywhere in your project.
<FormKit validation="required|monday" />
To customize the error message which shows up when your custom validation fails, follow the instructions here.
To add a validation to a specific input use the validation-rules
prop.
Your custom rules probably need a custom message — the next section of the docs will cover that.
There are several ways to customize your validation message. The most basic of which is to use the validation-label
prop — allowing you to change the name of the field as used in the pre-defined validation messages.
If you need to be more specific you have two options:
You can easily override validation messages directly on your FormKit
input by providing an object of strings or functions.
To override a validation message on a single FormKit input, add the validation-messages
prop with an object of rule names and a corresponding message.
If you need more power for your validation rules, you can use a function instead of a string. The function is passed a context object.
Behavior | Description |
---|---|
args | An array of arguments passed to the rule. For example 'Vue', 'React', 'Angular' from the rule is:Vue,React,Angular . |
name | The name of the field (first available from: validation-label , label , then name ). |
node | The FormKit core node . |
Let’s re-write the above example using a function instead of a string for even more control of the validation-messages
prop:
If there are validation rule messages you'd like to override (or add) across your entire project, you can define those message rules when registering FormKit under the language key you'd like to override:
import { createApp } from 'vue'
import App from './App.vue'
import { plugin, defaultConfig } from '@formkit/vue'
import monday from './my-custom-rules/monday'
// prettier-ignore
createApp(App).use(plugin, defaultConfig({
messages: {
en: {
validation: {
required({ name }) {
return `Please fill out the ${name} field.`
}
}
}
}
})).mount('#app')
If you would like to render an input’s validation messages outside of the <FormKit />
component, you can leverage the <FormKitMessages />
component by passing the input’s node as a prop. Using this component disables the default display of messages (located beneath the input) and moves them to wherever the <FormKitMessages />
component is located:
FormKit 1.0.0 introduced the FormKitSummary component which provides an "out of the box" solution to for displaying all the validation messages in a given form or subtree.
To get all the validation messages from an input’s core node, you can use the getValidationMessages
function exported from @formkit/validation
. This function will recursively check the given node and all children for validation messages and return a Map of core nodes to validation messages, making it ideal for use with forms:
Trying to manually trigger validation is an anti-pattern in FormKit and should be avoided. Validation is continually computed via fine-grained reactivity. If a value or prop that is used in a validation rule changes, the validation will be automatically be re-run. This ensures validity state, settlement state, submission state and any other validation-related properties can always be trusted.