You know what they say, you can not trust a thief or a murderer. You know who you can trust even less? That's right, the u s e r 😤. Therefore we need to strictly watch their every step and every action. Especially when we ask THEM (dear god) to input something in a form and send it to us (YIKES).
-
Make sure you clone this repository or install it with npm
npm i -S git+https://github.com/dolanske/v-valid.git
-
Set up your component
import { minLength, required, type, useValidation, validateIf } from '@dolanske/validate' import { computed, reactive } from 'vue' // Create your form const form = reactive({ value: [1, 2, 3], info: { contact: 'the_value_should_be_an_email' } }) // Create rules your form must conform to const rules = { // Rule keys must match the keys of your form value: { // Value is required required, // Using a helper, we can add conditional validations // Here we check if length of value is larger than 1 but ONLY if the value is an array shouldCheckType: validateIf( () => Array.isArray(form.value), minLength(1) ) }, // You can also nest rules info: { contact: { required, email } } } // Create your validation instance const { validate, errors, reset } = useValidation(form, rules)
-
Trigger form validation whenever and wherever you want
async function onSubmit(e) { e.preventDefault() validate() // ctx is an object which contains information about validation checks .then((ctx) => { /* Executes if validation passes */ }) .catch((ctx) => { /* Executes if validation fails */ // Extract a rule property for its information const { info } = ctx info.contact.id // 'contact' info.contact.value // 'the_value_should_be_an_email' info.contact.invalid // 'true' info.contact.errors.email // 'Value must be in a valid email format' }) } // You can also write the same function like this async function onSubmit(e) { e.preventDefault() try { await validate() } catch (errors: any) { // Handle errors or reset form // Resetting form clears all errors though, so it is recommended to display // them in some manner and reset them when user begins using the form again reset() } }
Main composable which is used to initiate form validation context as well as return validation methods.
form
reactive form objectrules
object or a computedRef objectoptions
autoclear
(default: false) resets all errors the first time a form is updated aftervalidation()
was ranproactive
(default: false) runs form validation on every input
Returns
validate(): Promise<State>
performs a form validation and resolves with the current State of the formreset(): void
clears all errors after form validationerrors
an object which contains all form fields and their statusstate
an object which includes state of the entire form
Collection of validators used to construct rule objects
Requires non-empty value.
const rules = {
name: { required }
}
Requires input to have a minimal specified length.
- Parameters
Ref<number> | number
min
- Works with
string
,Set<any>
,Map<any, any>
,any[]
andObject
const rules = {
name: { minLength: minLength(10) }
}
Requires input to have a maximum specified length.
- Parameters
Ref<number> | number
max
- Works with
string
,Set<any>
,Map<any, any>
,any[]
,Object
const rules = {
name: { minLength: minLength(10) }
}
Input must be a string and excluding spaces must be equal or greater to the provided min value.
- Parameters
Ref<number> | number
min - Minimum allowed string length
- Works with
string
const rules = {
value: {
// A B C D E F => false
// A B C D E F G => true
min: minLenNoSpace(7)
}
}
Input must be a string and excluding spaces must be equal or lesser to the provided max value.
- Parameters
Ref<number> | number
max - Maximum allowed string length
- Works with
string
const rules = {
value: {
// H e l l 0 => true
// Bummer => false
max: maxLenNoSpace(5)
}
}
Requires input to be a number or Date within the specified bounds.
- Parameters
Ref<number> | number | Date
minRef<number> | number | Date
max
- Works with
number
,Date
const rules = {
numberVal: { between: between(0, 10) },
dateVal: {
between: between(new Date('12/24/2020'), new Date('12/24/2022').getTime())
}
}
Requires input to be a valid URL.
Requires input to be a valid email address.
Requires input to be a number and contain decimals.
Checks wether an input contains any special characters
Requires input to be the same as the provided value in the rule.
- Parameters
Ref<any> | any
valueboolean
(default: false) lenient - wether to only compare based on value or value and type (eg.==
vs===
)
- Works with
any
const rules = {
name: { sameAs: sameAs('Hello world') }
}
Requires value to match the provided regular expression check.
- Parameters
string | RegExp
regex
- Works with
string
// Checks wether string contains only letters and numbers
const rules = {
name: {
noSpecialChars: match(/[^a-zA-Z0-9]/)
}
}
Checks wether string input contains certain words or characters. If you write multiple words. It will check against each word individually.
- Parameters
string | string[]
items - Words to check forboolean
(default: false) exact - Wether to match against the entire input string or split it by spaces. Default to true
- Works With
string
const rules = {
value: {
// Input: 'Hello Dear World' => false
containsExact: contains('Hello World', true),
// Input: 'Hello World' => true
containsSome: contains('Hello Dear World')
}
}
Checks wether the input value is a string and starts or ends with the provided parameter. You can optionally specify the position where the check begins in the input value
- Parameters
string | Ref<string>
String we are matching againstnumber
Starting position of the matching- Note: When using
endsWith
, the position starts at the end and goes backwards
- Note: When using
- Works with
string
const rules = {
value: {
// Input 'Hello World' => true
start: startsWith('llo', 2),
// Input 'Hello World' => false
endsBad: endsWith('Hello')
}
}
This is a special object rule in which you need to specify the type you want to check against.
Note, each type check is also available as a standalone import without using the type
object. Only difference is
that you need to prefix it.
// This import method
import { isMap, isStr } from 'v-valid'
// Equals to this one
import { type } from 'v-valid'
const { str, map } = type
- Available type checks
type.str
- requires value to be an instance ofstring
type.num
- requires value to be an instance ofnumber
type.arr
- requires value to be an instance ofArray
type.obj
- requires value to be an instance ofObject
type.set
- requires value to be an instance ofSet
type.map
- requires value to be an instance ofMap
type.date
- requires value to be an instance ofDate
type.symbol
- requires value to be an instance ofSymbol
const rules = {
name: { array: type.arr }
}
Allows you to add a custom error message to ant validation rule.
- Parameters
string | Label
labelValidationRule | ValidationRuleObject
rule
const rules = {
name: {
required: withLabel('You MUST fill this input!!', required)
}
}
We can also use a method instead of a string when creating custom label. This method receives the validated value
as the first parameter and all the subsequent parameters from the validation rule. If there are any.
const rules = {
name: {
between: withLabel(
(value, min, max) =>
`The value (${value}) must fit between ${min} and ${max}`,
// If error occurs, the message will read like this:
// 'The value (<value>) must fit between 5 and 10'
between(5, 10)
)
}
}
Used when we want to apply multiple rules together into one.
and(...ValidationRule[])
Requires all rules to be passing to resolveor(...ValidationRule[])
Requires at least one rule to be passing to resolve
const rules = {
name: {
// We want the value to be an array with at least 10 items in it
group: and(type.arr, minLength(10))
}
}
Used in situations where we want to invert a rule results. Can also be used with multiple rules, only resolving when all of them are failing.
const rules = {
name: {
// We want the input value to be anything but a string
notString: not(type.str)
}
}
Performs validation if the provided condition is met. Due to implementation limits, you can't use a rule as a condition. For that please use the and
helper.
- Parameters
boolean | () => boolean | Ref<boolean> | Promise<boolean>
conditionValidationRule
rule
const rules = {
name: {
// We want to check min length of value but only if value is an array
minLength: validateIf(Array.isArray(form.value), minLength(5)),
// If value is not a number, required it to match "Hello World"
sameAs: validateIfNot(typeof form.value === 'number', sameAs('Hello World'))
}
}
Helpers used to create validation rules
- Parameters
(value: any, args: Record<string, unknown>) => boolean | Promise<boolean>
rulestring | Label | undefined
label
// Define rule without any parameters
const required = $def(value => value !== undefined && value !== null, 'Value is required')
// Defining rules with parameters
// Rule which requires value to be an array and be at least n length
const arrAndMinLen = $defParam < { length: number } > (
(value, { length }) => isArray(value) && value.length >= length,
(_, { length }) => `Array with at least ${length} length`
)
// Asynchronous rule, the main use case here is validating
// login passwords or other API related things
const checkPassword = $def(
password =>
new Promise((resolve) => {
const result = await someApiCall(password)
resolve(result)
}),
'Incorrect password. Please try again.'
)
Perform a synthetic validation outside of any validation scope.
- Parameters
ValidationRule
rulevalue
any
const result = $test(minLength(5), [1, 2, 3]) // False
const result = $test(maxLength(5), [1, 2, 3]) // True
const result = $test(type.symbol, Symbol('Symbol')) // True
// With `and`, `not`, `or` and any async custom validators we have to await the returned promise
const result = await $test(or(type.str, type.num), 'Hello World') // True