1š
I think I found a way to achieve this.
Since iām not comfortable with Vue, Iām very open to comments and advices about this solution.
In the Form, I provide the vuelidate object but making it reactive using the computed function :
<!-- Form.vue -->
setup() {
return {
v$: useVuelidate(),
}
},
provide() {
return {
v$: computed(() => this.v$) // NOTE : to make injections reactively linked to the provider, we need to provide a computed property using the computed() function + To make injections automatically unwrap computed refs in Vue < 3.3, we need to set app.config.unwrapInjectedRef to true.
}
},
In this way, in could easily retrieve the vuelidate object (v$) using inject
in the child component avoiding props drilling.
<!-- Input.vue -->
<template>
<input
type="text"
v-model="modelLocal"
>
<span>{{ getErrors() }}</span>
</template>
<script>
export default {
inject: ['v$'],
emits: ['update:modelValue'],
props: {
modelValue: {
required: true,
},
path: {
required: true,
},
},
computed: {
modelLocal: {
get() {
return this.modelValue
},
set(value) {
this.$emit('update:modelValue', value)
}
},
},
methods: {
getErrors(){
return this.v$.$errors ? this.v$.$errors.filter((item)=> item.$propertyPath === this.path).map(e => e.$message) : ''
}
}
}
</script>
Note that I also added a getErrors() method on the Input and added a prop "path" to know which error I have to retrieve from the vuelidate object.
The input is now called like that:
<Input
v-model="data.field"
path="data.field"
></Input>
š¤Aurelien
Source:stackexchange.com