OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

How to use defineModel with vee-validate?

  • Thread starter Thread starter TinyTiger
  • Start date Start date
T

TinyTiger

Guest
I'm trying to build a Vue form using vee-validation with Composition API and zod.

The form validation is working correctly, but I want to use the new Vue 3.4 defineModel ref for the form input instead of the ref returned by vee-validate.

I have a working solution by adding a watch to each field, but on large forms that quickly becomes very verbose.

Is there a better way of linking the my own defineModel ref to the vee-validate ref?

Here is a live example: https://stackblitz.com/edit/nuxt-starter-bbrhtj?file=components/MyForm.vue

Code:
<template>
  <form class="flex flex-col gap-6 m-6">
    <div class="flex flex-col gap-2">
      <label for="businessName">Business Name</label>
      <InputText
        id="businessName"
        v-model="businessName"
        v-bind="businessNameAttrs"
      />
      <div class="text-xs text-red-500">
        {{ errors.businessName }}
      </div>
    </div>

    <Button @click="handleClick">Validate</Button>
  </form>
</template>

<script setup lang="ts">
import { defineComponent } from 'vue';
import { z } from 'zod';

// I want to use this as the v-model
const businessName = defineModel<string>('businessName');

const formSchema = toTypedSchema(
  z.object({
    businessName: z
      .string({ required_error: 'Business Name is required' })
      .min(1, { message: 'Business Name is required' }),
  })
);

const { errors, defineField, validate } = useForm({
  validationSchema: formSchema,
});

// But vee-validate requires us to use this destructured ref for the input validation
const [businessNameVee, businessNameAttrs] = defineField('businessName');

// One possible workaround is creating a watch for each field but with lots of form fields it quickly becomes very verbose
watch(businessName, () => {
  businessNameVee.value = businessName.value;
});

const handleClick = () => {
  validate();
};
</script>

<p>I'm trying to build a Vue form using <a href="https://vee-validate.logaretm.com/v4/integrations/zod-schema-validation/" rel="nofollow noreferrer">vee-validation with Composition API and zod</a>.</p>
<p>The form validation is working correctly, but I want to use the new Vue 3.4 <a href="https://vuejs.org/api/sfc-script-setup#definemodel" rel="nofollow noreferrer">defineModel</a> ref for the form input instead of the ref returned by vee-validate.</p>
<p>I have a working solution by adding a watch to each field, but on large forms that quickly becomes very verbose.</p>
<p>Is there a better way of linking the my own defineModel ref to the vee-validate ref?</p>
<p>Here is a live example: <a href="https://stackblitz.com/edit/nuxt-starter-bbrhtj?file=components/MyForm.vue" rel="nofollow noreferrer">https://stackblitz.com/edit/nuxt-starter-bbrhtj?file=components/MyForm.vue</a></p>
<pre class="lang-Vue prettyprint-override"><code><template>
<form class="flex flex-col gap-6 m-6">
<div class="flex flex-col gap-2">
<label for="businessName">Business Name</label>
<InputText
id="businessName"
v-model="businessName"
v-bind="businessNameAttrs"
/>
<div class="text-xs text-red-500">
{{ errors.businessName }}
</div>
</div>

<Button @click="handleClick">Validate</Button>
</form>
</template>

<script setup lang="ts">
import { defineComponent } from 'vue';
import { z } from 'zod';

// I want to use this as the v-model
const businessName = defineModel<string>('businessName');

const formSchema = toTypedSchema(
z.object({
businessName: z
.string({ required_error: 'Business Name is required' })
.min(1, { message: 'Business Name is required' }),
})
);

const { errors, defineField, validate } = useForm({
validationSchema: formSchema,
});

// But vee-validate requires us to use this destructured ref for the input validation
const [businessNameVee, businessNameAttrs] = defineField('businessName');

// One possible workaround is creating a watch for each field but with lots of form fields it quickly becomes very verbose
watch(businessName, () => {
businessNameVee.value = businessName.value;
});

const handleClick = () => {
validate();
};
</script>
</code></pre>
 

Latest posts

Top