Form validation is an important part of any app.
In this article, we’ll look at how to use Vee-Validate 4 in our Vue 3 app for form validation.
Call Set Form Validation Methods from Form’s ref
We can access the setFieldError and setErrors methods from the Form component’s ref.
For example, we can write:
<template>
  <Form @submit="onSubmit" ref="myForm">
    <Field name="email" as="input" />
    <ErrorMessage name="email" />
    <br />
    <Field name="password" as="input" />
    <ErrorMessage name="password" />
    <br />
    <input type="submit" />
  </Form>
</template>
<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";
export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {
    const schema = yup.object().shape({
      email: yup.string().required().email(),
      name: yup.string().required(),
      password: yup.string().required().min(8),
    });
    return {
      schema,
    };
  },
  methods: {
    onSubmit(values) {
      this.$refs.myForm.setFieldError("email", "this email is already taken");
      this.$refs.myForm.setErrors({
        email: "this field is already taken",
        password: "someone already has this password",
      });
    },
  },
};
</script>
We call setFieldError and setErrors from the form’s ref.
Validating Nested Objects
We can validate nested form objects with the Field component.
For example, we can write:
<template>
  <Form @submit="onSubmit" :validation-schema="schema">
    <Field name="links.twitter" type="url" />
    <ErrorMessage name="links.twitter" />
    <br />
    <Field name="links.github" type="url" />
    <ErrorMessage name="links.github" />
    <br />
    <button>Submit</button>
  </Form>
</template>
<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";
export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {
    const schema = yup.object().shape({
      links: yup.object().shape({
        twitter: yup.string().url(),
        github: yup.string().url(),
      }),
    });
    return {
      schema,
    };
  },
  methods: {
    onSubmit(values) {
      alert(JSON.stringify(values, null, 2));
    },
  },
};
</script>
We set the name attribute to the path to the field we want to validate in the Field and ErrorMessage components.
In the schema object, we do the same thing.
We call yup.object().shape() and add the links property inside the object we pass in as the argument.
Validating Nested Arrays
We can also use Vee-Validate 4 to validate nested arrays.
For instance, we can write:
<template>
  <Form @submit="onSubmit" :validation-schema="schema">
    <Field name="links[0]" type="url" />
    <ErrorMessage name="links[0]" />
    <br />
    <Field name="links[1]" type="url" />
    <ErrorMessage name="links[1]" />
    <br />
    <button>Submit</button>
  </Form>
</template>
<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";
export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {
    const schema = yup.object().shape({
      links: yup.array().of(yup.string().url()),
    });
    return {
      schema,
    };
  },
  methods: {
    onSubmit(values) {
      alert(JSON.stringify(values, null, 2));
    },
  },
};
</script>
to add the array validation.
We can check if an array of strings is a URL by writing:
yup.array().of(yup.string().url())
Composition API
We can add validation to our Vue 3 components if we use the composition API.
To do this, we write:
<template>
  <Form @submit="onSubmit" v-slot="{ errors }" :validation-schema="schema">
    <Field name="user.name" as="input" />
    <span id="nameErr">{{ errors["user.name"] }}</span>
    <br />
    <Field name="user.addresses[0]" as="input" id="address" />
    <span id="addrErr">{{ errors["user.addresses[0]"] }}</span>
    <br />
    <button id="submit">Submit</button>
  </Form>
</template>
<script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";
export default {
  components: {
    Form,
    Field,
  },
  setup() {
    return {
      schema: yup.object({
        user: yup.object({
          name: yup.string().required(),
          addresses: yup.array().of(yup.string().required()),
        }),
      }),
      onSubmit(values) {
        console.log(values);
      },
    };
  },
};
</script>
The setUp method returns the schema reactive property and the onSubmit method.
Conclusion
We can validate forms with the composition API and validate objects and nested arrays.
