Skip to content

Function: useValidation()

ts
function useValidation<TSchema>(
  fullSchema: MaybeRef<TSchema>,
  formInitialValues: MaybeRef<Record<string, any>>,
  onSubmit: (values: DataTypeOf<TSchema>) => MaybePromise<void>,
  additional: MaybeRef<Record<string, string>>,
  overrides: MaybeRef<
    Partial<
      Record<
        | "alternatives.all"
        | "alternatives.any"
        | "alternatives.match"
        | "alternatives.one"
        | "alternatives.types"
        | "any.custom"
        | "any.default"
        | "any.failover"
        | "any.invalid"
        | "any.only"
        | "any.ref"
        | "any.required"
        | "any.unknown"
        | "array.base"
        | "array.excludes"
        | "array.hasKnown"
        | "array.hasUnknown"
        | "array.includes"
        | "array.includesRequiredBoth"
        | "array.includesRequiredKnowns"
        | "array.includesRequiredUnknowns"
        | "array.length"
        | "array.max"
        | "array.min"
        | "array.orderedLength"
        | "array.sort"
        | "array.sort.mismatching"
        | "array.sort.unsupported"
        | "array.sparse"
        | "array.unique"
        | "boolean.base"
        | "date.base"
        | "date.format"
        | "date.greater"
        | "date.less"
        | "date.max"
        | "date.min"
        | "date.format.iso"
        | "date.format.javascript"
        | "date.format.unix"
        | "function.arity"
        | "function.class"
        | "function.maxArity"
        | "function.minArity"
        | "number.base"
        | "number.greater"
        | "number.infinity"
        | "number.integer"
        | "number.less"
        | "number.max"
        | "number.min"
        | "number.multiple"
        | "number.negative"
        | "number.port"
        | "number.positive"
        | "number.precision"
        | "number.unsafe"
        | "object.and"
        | "object.assert"
        | "object.base"
        | "object.instance"
        | "object.length"
        | "object.max"
        | "object.min"
        | "object.missing"
        | "object.nand"
        | "object.oxor"
        | "object.pattern.match"
        | "object.refType"
        | "object.regex"
        | "object.rename.multiple"
        | "object.rename.override"
        | "object.schema"
        | "object.unknown"
        | "object.with"
        | "object.without"
        | "object.xor"
        | "string.alphanum"
        | "string.base"
        | "string.base64"
        | "string.creditCard"
        | "string.dataUri"
        | "string.domain"
        | "string.email"
        | "string.empty"
        | "string.guid"
        | "string.hex"
        | "string.hexAlign"
        | "string.hostname"
        | "string.ip"
        | "string.ipVersion"
        | "string.isoDate"
        | "string.isoDuration"
        | "string.length"
        | "string.lowercase"
        | "string.max"
        | "string.min"
        | "string.normalize"
        | "string.token"
        | "string.pattern.base"
        | "string.pattern.name"
        | "string.pattern.invert.base"
        | "string.pattern.invert.name"
        | "string.trim"
        | "string.uri"
        | "string.uriCustomScheme"
        | "string.uriRelativeOnly"
        | "string.uppercase"
        | "symbol.base"
        | "symbol.map"
        | "binary.base"
        | "binary.length"
        | "binary.max"
        | "binary.min"
        | "bigint.base"
        | "bigint.greater"
        | "bigint.less"
        | "bigint.max"
        | "bigint.min"
        | "bigint.multiple"
        | "bigint.negative"
        | "bigint.positive"
        | "datetime.base"
        | "datetime.exactly"
        | "datetime.equals"
        | "datetime.after"
        | "datetime.greater"
        | "datetime.before"
        | "datetime.less"
        | "datetime.afterOrEqual"
        | "datetime.min"
        | "datetime.beforeOrEqual"
        | "datetime.max"
        | "datetime.weekend"
        | "datetime.weekday"
        | "phone.base"
        | "phone.invalid"
        | "phone.fixedLine"
        | "phone.mobile"
        | "phone.strictFixedLine"
        | "phone.strictMobile"
        | "phone.fixedLineOrMobile"
        | "phone.tollFree"
        | "phone.premiumRate"
        | "phone.sharedCost"
        | "phone.voip"
        | "phone.personalNumber"
        | "phone.pager"
        | "phone.uan"
        | "phone.voicemail"
        | "phone.unknown"
        | "phone.types",
        string
      >
    >
  >,
  options: MaybeRef<AsyncValidationOptions>,
  name: string,
  debug: MaybeRef<boolean>,
  onPreventedSubmit: (
    values: DataTypeOf<TSchema>,
    error: ValidationError,
  ) => MaybePromise<void>,
  fieldLabels: MaybeRef<Record<string, string>>,
  commonFieldOptions: MaybeRef<Record<string, any>>,
  specificFieldOptions: MaybeRef<Record<string, Record<string, any>>>,
): {
  doFormSubmit: (e?: Event) => Promise<MaybePromise<void> | undefined>;
  doResetForm: (
    state?: Partial<FormState<any>>,
    opts?: Partial<ResetFormOpts>,
  ) => void;
  forceUpdateInitialValues: () => void;
  forceUpdateSchema: () => void;
  formBindings: ComputedRef<FormHTMLAttributes>;
  formErrorBag: Ref<
    Partial<Record<string, string[]>>,
    Partial<Record<string, string[]>>
  >;
  formErrors: ComputedRef<Partial<Record<string, string | undefined>>>;
  formFieldBindings: ComputedRef<Record<string, ValidationFieldBindings<any>>>;
  formIsDirty: ComputedRef<boolean>;
  formIsPending: ComputedRef<boolean>;
  formIsSubmitting: Ref<boolean, boolean>;
  formIsTouched: ComputedRef<boolean>;
  formIsValid: ComputedRef<boolean>;
  formIsValidating: Ref<boolean, boolean>;
  formSubmitCount: Ref<number, number>;
  formValues: any;
  setFieldTouched: (field: string, isTouched: boolean) => void;
  setFieldValue: (field: string, value: any) => void;
  setTouched: (fields: boolean | Partial<Record<string, boolean>>) => void;
  setValues: (fields: any, shouldValidate?: boolean) => void;
  useField: (
    path: string,
    options?: {
      validateOnBlur?: boolean;
      validateOnChange?: boolean;
      validateOnInput?: boolean;
      validateOnModelUpdate?: boolean;
    },
  ) => ComputedRef<ValidationFieldBindings<any>>;
  validate: (
    opts?: Partial<ValidationOptions$1>,
  ) => Promise<FormValidationResult<any, any>>;
  validateField: <TPath>(
    field: TPath,
    opts?: Partial<ValidationOptions$1>,
  ) => Promise<ValidationResult<any>>;
  validationSchema: ShallowRef<ObjectSchema<any>, ObjectSchema<any>>;
};

Enterprise-grade form validation composable that bridges Joi schemas with VeeValidate and Vuetify. Provides comprehensive form state management, validation, and field binding generation.

Type Parameters

Type ParameterDescription
TSchema extends SchemaThe Joi schema type

Parameters

ParameterTypeDefault valueDescription
fullSchemaMaybeRef<TSchema>undefinedJoi schema defining validation rules for the entire form
formInitialValuesMaybeRef<Record<string, any>>undefinedInitial values for form fields (determines which fields are active)
onSubmit(values: DataTypeOf<TSchema>) => MaybePromise<void>undefinedForm submission handler receiving validated form values
additionalMaybeRef<Record<string, string>>{}Additional custom validation messages not in standard Joi set
overridesMaybeRef<Partial<Record< | "alternatives.all" | "alternatives.any" | "alternatives.match" | "alternatives.one" | "alternatives.types" | "any.custom" | "any.default" | "any.failover" | "any.invalid" | "any.only" | "any.ref" | "any.required" | "any.unknown" | "array.base" | "array.excludes" | "array.hasKnown" | "array.hasUnknown" | "array.includes" | "array.includesRequiredBoth" | "array.includesRequiredKnowns" | "array.includesRequiredUnknowns" | "array.length" | "array.max" | "array.min" | "array.orderedLength" | "array.sort" | "array.sort.mismatching" | "array.sort.unsupported" | "array.sparse" | "array.unique" | "boolean.base" | "date.base" | "date.format" | "date.greater" | "date.less" | "date.max" | "date.min" | "date.format.iso" | "date.format.javascript" | "date.format.unix" | "function.arity" | "function.class" | "function.maxArity" | "function.minArity" | "number.base" | "number.greater" | "number.infinity" | "number.integer" | "number.less" | "number.max" | "number.min" | "number.multiple" | "number.negative" | "number.port" | "number.positive" | "number.precision" | "number.unsafe" | "object.and" | "object.assert" | "object.base" | "object.instance" | "object.length" | "object.max" | "object.min" | "object.missing" | "object.nand" | "object.oxor" | "object.pattern.match" | "object.refType" | "object.regex" | "object.rename.multiple" | "object.rename.override" | "object.schema" | "object.unknown" | "object.with" | "object.without" | "object.xor" | "string.alphanum" | "string.base" | "string.base64" | "string.creditCard" | "string.dataUri" | "string.domain" | "string.email" | "string.empty" | "string.guid" | "string.hex" | "string.hexAlign" | "string.hostname" | "string.ip" | "string.ipVersion" | "string.isoDate" | "string.isoDuration" | "string.length" | "string.lowercase" | "string.max" | "string.min" | "string.normalize" | "string.token" | "string.pattern.base" | "string.pattern.name" | "string.pattern.invert.base" | "string.pattern.invert.name" | "string.trim" | "string.uri" | "string.uriCustomScheme" | "string.uriRelativeOnly" | "string.uppercase" | "symbol.base" | "symbol.map" | "binary.base" | "binary.length" | "binary.max" | "binary.min" | "bigint.base" | "bigint.greater" | "bigint.less" | "bigint.max" | "bigint.min" | "bigint.multiple" | "bigint.negative" | "bigint.positive" | "datetime.base" | "datetime.exactly" | "datetime.equals" | "datetime.after" | "datetime.greater" | "datetime.before" | "datetime.less" | "datetime.afterOrEqual" | "datetime.min" | "datetime.beforeOrEqual" | "datetime.max" | "datetime.weekend" | "datetime.weekday" | "phone.base" | "phone.invalid" | "phone.fixedLine" | "phone.mobile" | "phone.strictFixedLine" | "phone.strictMobile" | "phone.fixedLineOrMobile" | "phone.tollFree" | "phone.premiumRate" | "phone.sharedCost" | "phone.voip" | "phone.personalNumber" | "phone.pager" | "phone.uan" | "phone.voicemail" | "phone.unknown" | "phone.types", string>>>{}Override standard Joi validation messages with custom ones
optionsMaybeRef<AsyncValidationOptions>{}Joi validation options (async validation settings)
namestring...Form instance name for debugging and component identification
debugMaybeRef<boolean>falseEnable debug logging for validation failures
onPreventedSubmit(values: DataTypeOf<TSchema>, error: ValidationError) => MaybePromise<void>...-
fieldLabelsMaybeRef<Record<string, string>>{}-
commonFieldOptionsMaybeRef<Record<string, any>>{}-
specificFieldOptionsMaybeRef<Record<string, Record<string, any>>>{}-

Returns

ts
{
  doFormSubmit: (e?: Event) => Promise<
     | MaybePromise<void>
    | undefined>;
  doResetForm: (state?: Partial<FormState<any>>, opts?: Partial<ResetFormOpts>) => void;
  forceUpdateInitialValues: () => void;
  forceUpdateSchema: () => void;
  formBindings: ComputedRef<FormHTMLAttributes>;
  formErrorBag: Ref<Partial<Record<string, string[]>>, Partial<Record<string, string[]>>>;
  formErrors: ComputedRef<Partial<Record<string, string | undefined>>>;
  formFieldBindings: ComputedRef<Record<string, ValidationFieldBindings<any>>>;
  formIsDirty: ComputedRef<boolean>;
  formIsPending: ComputedRef<boolean>;
  formIsSubmitting: Ref<boolean, boolean>;
  formIsTouched: ComputedRef<boolean>;
  formIsValid: ComputedRef<boolean>;
  formIsValidating: Ref<boolean, boolean>;
  formSubmitCount: Ref<number, number>;
  formValues: any;
  setFieldTouched: (field: string, isTouched: boolean) => void;
  setFieldValue: (field: string, value: any) => void;
  setTouched: (fields:
     | boolean
    | Partial<Record<string, boolean>>) => void;
  setValues: (fields: any, shouldValidate?: boolean) => void;
  useField: (path: string, options?: {
     validateOnBlur?: boolean;
     validateOnChange?: boolean;
     validateOnInput?: boolean;
     validateOnModelUpdate?: boolean;
  }) => ComputedRef<ValidationFieldBindings<any>>;
  validate: (opts?: Partial<ValidationOptions$1>) => Promise<FormValidationResult<any, any>>;
  validateField: <TPath>(field: TPath, opts?: Partial<ValidationOptions$1>) => Promise<ValidationResult<any>>;
  validationSchema: ShallowRef<ObjectSchema<any>, ObjectSchema<any>>;
}

Object containing form state, field bindings, validation methods, and nested field helper

NameTypeDefault value
doFormSubmit()(e?: Event) => Promise< | MaybePromise<void> | undefined>-
doResetForm()(state?: Partial<FormState<any>>, opts?: Partial<ResetFormOpts>) => voidresetForm
forceUpdateInitialValues()() => voidupdateInitialValues
forceUpdateSchema()() => void-
formBindingsComputedRef<FormHTMLAttributes>-
formErrorBagRef<Partial<Record<string, string[]>>, Partial<Record<string, string[]>>>errorBag
formErrorsComputedRef<Partial<Record<string, string | undefined>>>errors
formFieldBindingsComputedRef<Record<string, ValidationFieldBindings<any>>>fieldBindings
formIsDirtyComputedRef<boolean>-
formIsPendingComputedRef<boolean>-
formIsSubmittingRef<boolean, boolean>isSubmitting
formIsTouchedComputedRef<boolean>-
formIsValidComputedRef<boolean>-
formIsValidatingRef<boolean, boolean>isValidating
formSubmitCountRef<number, number>submitCount
formValuesany-
setFieldTouched()(field: string, isTouched: boolean) => void-
setFieldValue()(field: string, value: any) => void-
setTouched()(fields: | boolean | Partial<Record<string, boolean>>) => void-
setValues()(fields: any, shouldValidate?: boolean) => void-
useField()(path: string, options?: { validateOnBlur?: boolean; validateOnChange?: boolean; validateOnInput?: boolean; validateOnModelUpdate?: boolean; }) => ComputedRef<ValidationFieldBindings<any>>-
validate()(opts?: Partial<ValidationOptions$1>) => Promise<FormValidationResult<any, any>>-
validateField()<TPath>(field: TPath, opts?: Partial<ValidationOptions$1>) => Promise<ValidationResult<any>>-
validationSchemaShallowRef<ObjectSchema<any>, ObjectSchema<any>>formSchema

Example

typescript
const schema = joi.object({
  name: joi.string().required(),
  email: joi.string().email().required(),
  settings: joi.object({
    theme: joi.string().valid("light", "dark"),
  }),
});

const { formFieldBindings, useField, formIsValid, doFormSubmit } =
  useValidation(
    schema,
    { name: "", email: "", settings: { theme: "light" } },
    async (values) => {
      await api.saveUser(values);
    },
  );

// Use flat bindings
const nameField = formFieldBindings.name;

// Use nested fields
const themeField = useField("settings.theme");