For people like me, coming here for guidance in the future with v4 of vee-validate together with Vue3 Composition API and Typescript, I'd like to suggest this answer. It works by adding each validate
method from useForm
to an array and then on form submit it will loop through the array to ensure all validators pass asynchronously.
formAggregator.ts
import { InjectionKey, provide, ref } from "vue";
type ValidatorMethodType = () => Promise<{ valid: boolean }>;
export const AddValidatorKey: InjectionKey<
(validator: ValidatorMethodType) => void
> = Symbol("AddValidatorKey");
export function useValidationAggregator() {
const validators = ref<ValidatorMethodType[]>([]);
// used by components to add validators to the array
const register = (validator: ValidatorMethodType) => {
validators.value.push(validator);
};
// provide this aggregator to components
provide(AddValidatorKey, register);
// run all validators
const validateAll = async () => {
return Promise.all(validators.value.map((v) => v()));
};
return {
validateAll,
register,
};
}
ParentComponent.vue
<template>
<form @submit.prevent="onSubmit">
<ChildComponent />
<button type="submit" :disabled="inSubmit">Submit</button>
</form>
</template>
<script setup>
import useValidationAggregator from "./formAggregator.ts"
const { validateAll } = useValidationAggregator();
// note: you can use register() to also add validator from the parent component
const inSubmit = ref(false);
const onSubmit = async () => {
try {
inSubmit.value = true;
// run all form validators
const results = await validateAll();
// ensure all are valid
if (results.some((r) => !r.valid)) {
return;
}
// todo: post form or whatever you need after validation passes
} finally {
inSubmit.value = false;
}
}
</script>
ChildComponent.vue
<template>
<!-- some validated fields -->
</template>
<script setup>
import { AddValidatorKey } from "./formAggregator.ts"
const { validate } = useForm({ ... setup validated fields ... });
// add this component's validator to the aggregator
const addValidator = inject(AddValidatorKey, () => {
throw new Error("No aggregator provided for inject");
});
addValidator(validate);
</script>