Form Validation (useKatluxForm)
Enterprise schema-based form management composable for Katlux components with zero runtime dependencies. Supports Standard Schema (@standard-schema/spec), Zod, and custom validators with automatic prop binding.
💡
Component-Level vs. Form-Level Validation
Katlux inputs natively support semantic validation props (:validation and :validationText). For individual component state rules and manual validation, see the Component Validation Showcase. useKatluxForm builds on top of those exact same component states to eliminate boilerplate across full multi-field forms.
Enterprise Schema Form with useKatluxForm
Fields validate once unfocused (blurred). Once invalid, errors clear immediately on change.
Reactive Form State Inspector
isDirtyfalse
isValidtrue
isSubmittingfalse
submitCount0
Current Form Values:
{
"name": "",
"email": "",
"password": "",
"role": "",
"acceptTerms": false
}TypeScript
// 1. Define schema (Standard Schema, Zod, or Custom)
import { useKatluxForm } from '@katlux/toolkit/composables'
const schema = {
safeParse: (data) => {
const issues = []
if (!data.name || data.name.trim().length < 3) {
issues.push({ path: ['name'], message: 'Full name must be at least 3 characters' })
}
if (!data.email?.includes('@')) {
issues.push({ path: ['email'], message: 'Valid email required' })
}
if (!data.password || data.password.length < 6) {
issues.push({ path: ['password'], message: 'Password must be at least 6 characters' })
}
if (!data.role) {
issues.push({ path: ['role'], message: 'Please select a role' })
}
if (!data.acceptTerms) {
issues.push({ path: ['acceptTerms'], message: 'You must accept the terms of service' })
}
return issues.length ? { success: false, error: { issues } } : { success: true, data }
}
}
// 2. Initialize composable
const { register, handleSubmit, values, errors, isSubmitting, reset } = useKatluxForm({
schema,
initialValues: { name: '', email: '', password: '', role: '', acceptTerms: false },
mode: 'onBlur'
})
// 3. Handle submission
const submitForm = handleSubmit(async (output) => {
await api.save(output)
})
// 4. Zero-boilerplate template binding
// KTextbox(label="Full Name" v-bind="register('name')")
// KTextbox(label="Email" v-bind="register('email')")
// KButton(type="primary" :loading="isSubmitting" @click="submitForm") Submit
useKatluxForm Options
Configuration parameters accepted by the useKatluxForm composable.
| Name | Type | Default | Description |
|---|---|---|---|
| initialValues | Record<string, any> | {} | Initial state dictionary for form fields. |
| schema | StandardSchema | ZodSchema | Function | undefined | Validation schema implementing Standard Schema spec, Zod safeParse, or a custom validator callback. |
| mode | 'onBlur' | 'onChange' | 'onSubmit' | 'onBlur' | Strategy for triggering field validation. |
| reValidateMode | 'onBlur' | 'onChange' | 'onSubmit' | 'onChange' | Trigger strategy when a field already has an active error. |
| focusOnError | boolean | true | Automatically focus the first invalid input element upon failed submission. |
Return Object & Binding Contract
The returned reactive properties and helpers for managing form state.
| Property / Method | Type | Description |
|---|---|---|
| register(path, options?) | Function | Returns { name, modelValue, 'onUpdate:modelValue', validation, validationText, onBlur } matching Katlux input props. |
| handleSubmit(onValid, onInvalid?) | Function | Submission wrapper executing validation, first-error focus management, and callback invocation. |
| values | Reactive<TValues> | Reactive object containing current form values. |
| errors | Ref<Record<string, string>> | Map of field dot-paths to their active error messages. |
| isDirty | ComputedRef<boolean> | True if any registered field has been modified by user keystroke. |
| isValid | ComputedRef<boolean> | True when the form has zero active errors. |
| isSubmitting | Ref<boolean> | True while an async onValid handler is in progress. |
| reset(newValues?) | Function | Restores form values to initial state and clears all errors, touched, and dirty flags. |