SuperForm
v1.0.0 · Last updated April 2026
Forms with declarative validation rules, real-time feedback, and HTMX integration. Complete documentation for all validation types, field types, and advanced patterns.
# Basic Usage
Add data-az-component="super-form" to any form element.
<form data-az-component="super-form"
action="/api/users"
method="POST">
<div data-az-field>
<label for="email">Email</label>
<input type="email"
id="email"
name="email"
data-az-validate="required,email">
<span data-az-error="email"></span>
</div>
<div data-az-field>
<label for="password">Password</label>
<input type="password"
id="password"
name="password"
data-az-validate="required,min:8">
<span data-az-error="password"></span>
</div>
<button type="submit">Submit</button>
</form>
# Validation Rules
Combine validation rules with commas. Parameters use colon syntax.
| Rule | Syntax | Description |
|---|---|---|
| required | required | Field must not be empty |
| Valid email format | ||
| min | min:8 | Minimum length (string) or value (number) |
| max | max:100 | Maximum length (string) or value (number) |
| between | between:1,10 | Value must be between min and max |
| pattern | pattern:^[A-Z]{2}[0-9]+$ | Match regex pattern |
| url | url | Valid URL format |
| phone | phone | Valid phone number |
| date | date | Valid date format |
| before | before:2025-01-01 | Date must be before specified |
| after | after:today | Date must be after specified |
| match | match:password | Value must match another field |
| different | different:old_password | Value must differ from another field |
| in | in:red,green,blue | Value must be one of listed options |
| not_in | not_in:admin,root | Value must not be in list |
| numeric | numeric | Must be a number |
| integer | integer | Must be an integer |
| alpha | alpha | Letters only |
| alphanumeric | alphanumeric | Letters and numbers only |
| accepted | accepted | Checkbox must be checked |
Custom Error Messages
<input type="email"
name="email"
data-az-validate="required,email"
data-az-message-required="Please enter your email address"
data-az-message-email="That doesn't look like a valid email">
Async Validation (Server-Side)
<input type="text"
name="username"
data-az-validate="required,min:3"
data-az-validate-async="/api/check-username"
data-az-validate-debounce="300">
# Field Types
SuperForm enhances various input types with consistent styling and behavior.
Text Input
<input type="text"
data-az-input
data-az-validate="required">
Textarea
<textarea data-az-input
data-az-autosize
data-az-validate="max:500">
</textarea>
Select
<select data-az-input
data-az-searchable
data-az-validate="required">
<option value="">Choose...</option>
</select>
Checkbox
<label data-az-checkbox>
<input type="checkbox"
data-az-validate="accepted">
<span>I agree</span>
</label>
Radio Group
<div data-az-radio-group
data-az-validate="required">
<label data-az-radio>
<input type="radio" value="a">
<span>Option A</span>
</label>
</div>
Date Picker
<input type="date"
data-az-input
data-az-datepicker
data-az-validate="after:today">
# Feedback & Indicators
Configure when and how validation feedback appears.
| Attribute | Values | Description |
|---|---|---|
| data-az-validate-on | "blur" | "input" | "change" | "submit" | When to trigger validation |
| data-az-show-valid | boolean | Show success state on valid fields |
| data-az-error-class | string | Class to add on invalid |
| data-az-valid-class | string | Class to add on valid |
| data-az-loading | selector | Element to show during async validation |
Error Display
<div data-az-field>
<label>Email</label>
<input type="email"
name="email"
data-az-validate="required,email"
data-az-validate-on="blur"
data-az-show-valid="true">
<!-- Error message container -->
<span data-az-error="email" class="text-red-500"></span>
<!-- Success indicator -->
<span data-az-valid="email" class="text-green-500 hidden">✓</span>
<!-- Character counter -->
<span data-az-counter="email">0/100</span>
</div>
# HTMX Integration
SuperForm integrates seamlessly with HTMX for async submissions.
<form data-az-component="super-form"
hx-post="/api/users"
hx-swap="none"
data-az-submit-loading="true">
<!-- Form fields... -->
<button type="submit" data-az-submit-button>
<span data-az-submit-text>Submit</span>
<span data-az-submit-loading class="hidden">Saving...</span>
</button>
</form>
Server-Side Validation Errors
HTTP 422 Unprocessable Entity
Content-Type: application/json
{
"errors": {
"email": "This email is already registered",
"password": "Password must contain at least one number"
}
}
Note: SuperForm automatically displays server-side errors in the corresponding data-az-error containers when the server returns a 422 response with the above format.
# Multi-Step Forms (Wizard)
Build step-by-step forms with validation per step.
<form data-az-component="super-form"
data-az-wizard="true">
<!-- Progress Indicator -->
<div data-az-wizard-progress>
<span data-az-wizard-step="1" class="active">Account</span>
<span data-az-wizard-step="2">Profile</span>
<span data-az-wizard-step="3">Confirm</span>
</div>
<!-- Step 1 -->
<div data-az-wizard-panel="1" class="active">
<h3>Account Details</h3>
<input name="email" data-az-validate="required,email">
<input name="password" data-az-validate="required,min:8">
<button type="button" data-az-wizard-next>Next</button>
</div>
<!-- Step 2 -->
<div data-az-wizard-panel="2">
<h3>Profile Info</h3>
<input name="name" data-az-validate="required">
<input name="phone" data-az-validate="phone">
<button type="button" data-az-wizard-prev>Back</button>
<button type="button" data-az-wizard-next>Next</button>
</div>
<!-- Step 3 -->
<div data-az-wizard-panel="3">
<h3>Confirm</h3>
<div data-az-wizard-summary></div>
<button type="button" data-az-wizard-prev>Back</button>
<button type="submit">Create Account</button>
</div>
</form>
# Conditional Logic
Show/hide fields and change validation based on other field values.
<!-- Trigger field -->
<select name="contact_method" data-az-input>
<option value="email">Email</option>
<option value="phone">Phone</option>
<option value="post">Post</option>
</select>
<!-- Conditional fields -->
<div data-az-field
data-az-show-if="contact_method=email">
<label>Email Address</label>
<input name="email"
data-az-validate="email"
data-az-required-if="contact_method=email">
</div>
<div data-az-field
data-az-show-if="contact_method=phone">
<label>Phone Number</label>
<input name="phone"
data-az-validate="phone"
data-az-required-if="contact_method=phone">
</div>
<div data-az-field
data-az-show-if="contact_method=post">
<label>Mailing Address</label>
<textarea name="address"
data-az-required-if="contact_method=post"></textarea>
</div>
Advanced Conditions
<!-- Multiple conditions (AND) -->
<div data-az-show-if="country=US,state=CA">
California-specific fields
</div>
<!-- OR conditions -->
<div data-az-show-if-any="type=business,type=enterprise">
Business fields
</div>
<!-- Not equal -->
<div data-az-show-if="subscription!=free">
Premium features
</div>
<!-- Field has any value -->
<div data-az-show-if="promo_code">
<input name="promo_code" data-az-validate="min:5">
</div>
# Events
| Event | Description | Detail |
|---|---|---|
| az:form:valid | Form passed all validation | { data } |
| az:form:invalid | Form has validation errors | { errors } |
| az:field:valid | Field passed validation | { field, value } |
| az:field:invalid | Field failed validation | { field, errors } |
| az:wizard:step | Wizard step changed | { from, to } |
| az:form:submit | Form submission started | { data } |
| az:form:success | Form submitted successfully | { response } |
| az:form:error | Form submission failed | { errors } |