alpidate
v3.0.6
Published
A model-based validation plugin for Alpine.js, inspired by Vuelidate.
Maintainers
Readme
alpidate
A lightweight validation plugin for Alpine.js inspired by Vuelidate.
Demo
Try the live demo here: Alpidate Live Demo
Installation
Via npm (Recommended for Module Bundlers)
You can install alpidate via npm:
npm install alpidateThen import and register:
import Alpine from 'alpinejs';
import alpidate from 'alpidate';
Alpine.plugin(alpidate);
Alpine.start();Via CDN (For Quick Prototyping or Static Sites)
You can load alpidate directly from a CDN like unpkg:
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/alpidate/dist/alpidate.cdn.js"></script>
<script>
document.addEventListener('alpine:init', () => {
Alpine.plugin(alpidate)
})
</script>Note: Ensure Alpine.js is loaded before alpidate. This uses the global alpidate export.
Usage
Setting Up Validation in a Component
Define validation rules inside the validations property and initialize validation in init():
Alpine.data('app', () => ({
init() {
// default: validation state stored on $v
this.$validation(this); // -> creates this.$v
}
// Validation rules
validations: {
'first_name': ['required', 'min:3'],
'last_name': ['required', 'min:3'],
'delivery_note': ['requiredIf:express_delivery,true', 'max:100'],
'email': ['required', 'email'],
'address': ['required', 'array'],
'address.*.name': ['required', 'min:2'],
'address.*.address': ['required', 'min:5'],
'address.*.phone': ['regex:^\\d{10}$']
},
// Form data
first_name: '',
last_name: '',
email: '',
express_delivery: false,
delivery_note : '',
address: [
{ name: '', address: '', phone: '' },
{ name: '', address: '', phone: '' }
]
}));Nested components / isolated validation state
If you use nested x-data components and need each component to keep its own validation state (instead of sharing the default $v), pass a custom key when initializing. This creates a separate validation tree under that key and prevents collisions/overwrites with parent components. All validation-related properties (e.g., state, $invalid, $touch, validate()) will be stored under the custom key, not the default $v:
// inside a nested component's init()
this.$validation(this, '$v2'); // -> creates this.$v2 (isolated)Supported Validation Rules
| Rule | Description |
|------------|--------------------------------------------------------------------------- |
| required | Ensures the field is not empty. |
| requiredIf | Ensures the field is required only if a specified condition is met, based on the value of another field. The condition is defined as requiredIf:field,expectedValue, where the field must match the expected value for the validation to apply. |
| numeric | The field must contain only numbers. |
| email | Validates an email format. |
| regex | Allows custom validation rules using regular expressions. |
| min:value | Specifies the minimum length or value. |
| max:value | Specifies the maximum length or value. |
| array | Ensures the field is an array. |
Nested models and array items are supported, for example:
// Nested model
'form.firstName': ['required', 'min:3']
// Array item validation using wildcard '*'
'address.*.name': ['required', 'min:2']
'address.*.phone': ['regex:^\\d{10}$']Accessing Validation State
All validation state is stored under the specified key (defaults to $v). Each model inside the validation state contains:
- Rule results: e.g.,
required,min,regex, etc. Each key shows whether that specific rule passed (false) or failed (true). - $invalid: Boolean indicating if any of the assigned rules failed for that model.
For array fields, use each to access per-item validation:
// Access validation for first item in the address array
this.$v.address.each[0].name.$invalid // true or false
this.$v.address.each[1].phone.regex // true or falseSpecial properties :
$v.$touch– Controls when validation messages appear. It remains false until you manually trigger validation with :
this.$v.validate();$v.$invalid– Boolean indicating whether any rule in the entire form fails. Whenever a model changes, its validation state updates automatically. Use $touch to delay showing errors until, for example, form submission.
For isolated / nested components:
If you initialized validation with a custom key (e.g., this.$validation(this, '$v2')), the validation tree and special props live under that key:
// init inside nested component
this.$validation(this, '$v2'); // creates this.$v2
// run full validation
this.$v2.validate();
// or validate a single model
this.$v2.validate('selectedAddress');Displaying Validation Errors in Template
Use the validation key to conditionally display validation errors in your template:
<span x-show="$v.first_name.$invalid && $v.$touch">
<small x-show="$v.first_name.required" class="text-red">First Name is required</small>
<small x-show="!$v.first_name.required && $v.first_name.min" class="text-red">Minimum 3 characters</small>
</span>
<template x-for="(addr, idx) in address" :key="idx">
<div>
<input x-model="addr.name" placeholder="Name">
<span x-show="$v.address.each[idx].name.$invalid && $v.$touch">
<small x-show="$v.address.each[idx].name.required" class="text-red">Address is required</small>
<small x-show="!$v.address.each[idx].name.required && $v.address.each[idx].name.min" class="text-red">Minimum 2 characters</small>
</span>
</div>
</template>For custom keys (e.g., $v2), replace $v with $v2 in the template:
<span x-show="$v2.first_name.$invalid && $v2.$touch">...</span>Understanding the Validation State
- Each model inside the validation state has an
$invalidproperty indicating if all assigned validation rules pass. $touchhelps control when validation messages appear (e.g., after form submission).- Array items are available via
arrayField.eachunder the validation key.
License
MIT License
