Form Validation & $validation
Avenx-JS includes a built-in declarative form validation engine (lib/core/validation/validator.js) integrated directly into AvenxComponent. Form input elements specify validation constraints using the data-ax-validate attribute. On user interaction (input/change events) and component updates, Avenx-JS automatically evaluates rules and populates the reactive this.state.$validation state object.
data-ax-validate Directive Syntax
Section titled “data-ax-validate Directive Syntax”The data-ax-validate directive is applied directly to <input>, <textarea>, and <select> elements.
1. Pipe-Delimited Rule Definitions
Section titled “1. Pipe-Delimited Rule Definitions”Combine multiple validation rules using the pipe (|) delimiter:
<input name="email" data-ax-bind="email" data-ax-validate="required|email"/>2. Rule Arguments
Section titled “2. Rule Arguments”Pass arguments to rules using a colon (:):
<input type="password" name="password" data-ax-bind="password" data-ax-validate="required|min:8"/>
<input type="password" name="confirmPassword" data-ax-bind="confirmPassword" data-ax-validate="required|same:password"/>3. Custom Validation Messages
Section titled “3. Custom Validation Messages”Custom error messages can be defined inline or via JSON maps:
Inline Custom Messages
Section titled “Inline Custom Messages”Append a custom error message after a second colon (:):
<input name="password" data-ax-bind="password" data-ax-validate="required:Password is mandatory|min:8:Must be at least 8 characters"/>JSON Message Map (data-ax-validate-messages)
Section titled “JSON Message Map (data-ax-validate-messages)”Provide custom messages per rule using a JSON string in data-ax-validate-messages:
<input name="username" data-ax-bind="username" data-ax-validate="required|min:4|alphanumeric" data-ax-validate-messages='{ "required": "Username cannot be empty", "min": "Username must be at least 4 characters", "alphanumeric": "Only letters and numbers are allowed" }'/>Built-in Validation Rules Reference
Section titled “Built-in Validation Rules Reference”Avenx-JS includes 10 built-in validation rules:
| Rule Name | Argument | Supported Types | Evaluation & Behavior | Default Error Message |
|---|---|---|---|---|
required |
None | boolean, Array, string |
Fails if boolean is false, array length is 0, or trimmed string is empty. |
Field is required |
email |
None | string |
Validates against regular expression /^[^\s@]+@[^\s@]+\.[^\s@]+$/. Empty strings pass unless required is present. |
Invalid email address |
min |
number |
number, Array, string |
Fails if numeric value, array length, or string character count is less than arg. |
Minimum length/value is <arg> |
max |
number |
number, Array, string |
Fails if numeric value, array length, or string character count exceeds arg. |
Maximum length/value is <arg> |
pattern / regex |
string |
string |
Evaluates string value against regular expression new RegExp(arg). |
Field format is invalid |
numeric / number |
None | string |
Fails if non-empty string does not match numeric format /^-?\d+(\.\d+)?$/. |
Must be a number |
alpha |
None | string |
Fails if non-empty string contains characters outside /^[a-zA-Z]+$/. |
Must contain only letters |
alphanumeric |
None | string |
Fails if non-empty string contains characters outside /^[a-zA-Z0-9]+$/. |
Must contain only letters and numbers |
url |
None | string |
Fails if non-empty string fails URL parsing via new URL(val). |
Invalid URL format |
same |
stateProp |
any |
Checks strict equality (===) against this.state[stateProp]. |
Must match <stateProp> |
Field Name Resolution
Section titled “Field Name Resolution”The validator determines the key name for each field in this.state.$validation by checking attributes on the element in order of priority:
nameattribute (e.g.name="user_email")data-ax-bindproperty (e.g.data-ax-bind="email")idattribute (e.g.id="email-input")- Fallback default string:
'field'
Reactive this.state.$validation Schema
Section titled “Reactive this.state.$validation Schema”When a component contains elements with data-ax-validate, Avenx-JS initializes and updates this.state.$validation with the following structure:
interface ValidationState { /** * True if all validated form fields in the component are valid; false otherwise. */ isValid: boolean;
/** * Maps field names to arrays of active validation error strings. */ errors: Record<string, string[]>;
/** * Detailed per-field validity information. */ fields: Record< string, { isValid: boolean; errors: string[]; } >;}Example $validation Object State
Section titled “Example $validation Object State”{ "isValid": false, "errors": { "email": ["Invalid email address"], "password": [] }, "fields": { "email": { "isValid": false, "errors": ["Invalid email address"] }, "password": { "isValid": true, "errors": [] } }}Component Instance Methods
Section titled “Component Instance Methods”Programmatic Validation (this.$validateElement(el))
Section titled “Programmatic Validation (this.$validateElement(el))”You can trigger validation programmatically on any DOM element by passing it to this.$validateElement(el):
// Programmatically validate an input elementconst emailInput = this.$element.querySelector('input[name="email"]');const errors = this.$validateElement(emailInput);
console.log(errors); // ['Invalid email address']Calling $validateElement evaluates the element’s rules against its current value, updates this.state.$validation reactively, and returns an array of active error messages.
Full Form Submit Example
Section titled “Full Form Submit Example”The following Single File Component example demonstrates form validation, error message rendering, dynamic CSS class binding (data-ax-class), and submit handling:
export default { state: { email: '', password: '', submitted: false, },
methods: { handleSubmit(event) { event.preventDefault(); this.state.submitted = true;
// Check form validity before submission if (!this.state.$validation.isValid) { console.warn('Form validation failed:', this.state.$validation.errors); return; }
console.log('Submitting form with data:', { email: this.state.email, password: this.state.password, }); }, },
template: ` <form @submit="handleSubmit"> <div class="form-group"> <label>Email Address</label> <input type="email" name="email" data-ax-bind="email" data-ax-validate="required|email" data-ax-class="{ 'has-error': state.$validation?.fields?.email?.isValid === false }" placeholder="you@example.com" /> <span data-ax-show="state.$validation?.errors?.email?.length > 0" class="error-text" > {{ state.$validation?.errors?.email?.[0] }} </span> </div>
<div class="form-group"> <label>Password</label> <input type="password" name="password" data-ax-bind="password" data-ax-validate="required:Password is required|min:8:Minimum 8 characters" data-ax-class="{ 'has-error': state.$validation?.fields?.password?.isValid === false }" placeholder="••••••••" /> <span data-ax-show="state.$validation?.errors?.password?.length > 0" class="error-text" > {{ state.$validation?.errors?.password?.[0] }} </span> </div>
<button type="submit" data-ax-disabled="!state.$validation?.isValid" > Sign In </button> </form> `,};