useValidation
The heart of the package: one call per form creates a validation context that is shared with every validation component in the subtree through provide/inject. Fields register themselves; the composable aggregates their state and drives the submit flow.
Calling useValidation() in a component whose ancestors already created a context returns that existing context, so nested components can freely access the same errors and helpers.
Importing
import { useValidation } from '@basmilius/validation';Usage
<template>
<FluxForm @submit="validated(submit)">
<ValidationNotice/>
<ValidationField
label="Email address"
:rules="[rules.required, rules.email]"
validation-key="email"
:value="form.email">
<FluxFormInput
v-model="form.email"
type="email"/>
</ValidationField>
<FluxPrimaryButton
:disabled="invalid"
is-submit
label="Save"/>
</FluxForm>
</template>
<script
lang="ts"
setup>
import { useValidation, ValidationField, ValidationNotice } from '@basmilius/validation';
import { reactive } from 'vue';
const form = reactive({
email: ''
});
const {invalid, rules, validated} = useValidation();
async function submit(): Promise<void> {
await service.update(form);
}
</script>Live validation
By default, fields validate when the form is submitted and keep re-validating while the user fixes the reported errors. Pass true to validate every field on each change instead:
const {invalid, rules, validated} = useValidation(true);The submit flow
validated(fn, close?) first validates the whole form. When valid, fn runs; when fn resolves, the optional close callback fires (handy for dialogs). Errors thrown by fn are mapped onto the form; see Server errors.
Escape hatch
The returned r$ is Regle's merged instance for the form. Use it for anything the simplified surface does not cover, such as $touch, $extractDirtyFields or per-instance inspection.
Type signature
declare function useValidation(isLive?: boolean): UseValidation;
interface UseValidation {
readonly errors: ComputedRef<ValidationErrors>;
readonly invalid: ComputedRef<boolean>;
readonly live: Readonly<Ref<boolean>>;
readonly r$: MergedScopedRegles;
readonly rules: ValidationRules;
readonly handleError: (err: unknown) => void;
readonly reset: () => void;
readonly validate: () => Promise<boolean>;
readonly validated: (fn: () => void | Promise<void>, close?: () => void) => Promise<void>;
}
type ValidationErrors = Record<string | symbol, string>;
const GLOBAL_ERROR_KEY: unique symbol;errors: flat map of client- and server-side error messages, keyed byvalidation-key(dot-notation for nested server errors) plusGLOBAL_ERROR_KEYfor request failures.invalid:truewhen there is at least one visible error. Before the first submit this isfalse, so submit buttons stay enabled until the user actually gets something wrong.handleError: the mapping used byvalidated(), exposed for manual try/catch flows.