Categories
Vue 3

Form Validation in a Vue 3 App with Vee-Validate 4 — Form Validation Rules

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.

Rules with Multiple Parameters

We can have global validation rules with multiple parameters.

To define and use them, we write:

<template>
  <Form @submit="onSubmit">
    <Field name="number" as="input" rules="required|min:0,100" />
    <ErrorMessage name="number" />
    <br />

    <button>Submit</button>
  </Form>
</template>

<script>
import { Form, Field, ErrorMessage, defineRule } from "vee-validate";

defineRule("required", (value) => {
  if (!value || !value.length) {
    return "This field is required";
  }
  return true;
});

defineRule("min", (value, [min, max]) => {
  if (!value || !value.length) {
    return true;
  }
  const numericValue = +value;
  if (numericValue < min) {
    return `This field must be greater than ${min}`;
  }
  if (numericValue > max) {
    return `This field must be less than ${max}`;
  }
  return true;
});

export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {},
  methods: {
    onSubmit(values) {
      alert(JSON.stringify(values, null, 2));
    },
  },
};
</script>

We define the min rule with the min and max parameters.

And we check against them to return the right validation result.

true means the value is valid.

Otherwise, we return an error message string.

Then in the rules prop, we combine the required rule with the min rule.

Schema Validation

We can add the rules to the validation schema.

For example, we can write:

<template>
  <Form @submit="submit" :validation-schema="schema" v-slot="{ errors }">
    <Field name="email" as="input" />
    <span>{{ errors.email }}</span>
    <br />

    <Field name="password" as="input" type="password" />
    <span>{{ errors.password }}</span>
    <br />

    <button>Submit</button>
  </Form>
</template>

<script>
import { Form, Field, defineRule } from "vee-validate";

defineRule("required", (value) => {
  if (!value || !value.length) {
    return "This field is required";
  }
  return true;
});

defineRule("email", (value) => {
  if (!value || !value.length) {
    return true;
  }
  if (!/[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}/.test(value)) {
    return "This field must be a valid email";
  }
  return true;
});

defineRule("minLength", (value, [limit]) => {
  if (!value || !value.length) {
    return true;
  }
  if (value.length < limit) {
    return `This field must be at least ${limit} characters`;
  }
  return true;
});

export default {
  components: {
    Form,
    Field,
  },
  data() {
    const schema = {
      email: "required|email",
      password: "required|minLength:8",
    };

    return {
      schema,
    };
  },
  methods: {
    onSubmit(values) {
      alert(JSON.stringify(values, null, 2));
    },
  },
};
</script>

We defined the required , email , and minLength rules.

Then we put them all in the schema object.

Then we set the validation-schema prop to the schema reactive property.

And then we display the error messages by getting the errors object from the slot props of the Form component.

Now when we use the form, the validation rules will be used to validate the form.

Conclusion

We can validate more complex forms with in our Vue 3 app with Vee-Validate 4.

Categories
Vue 3

Form Validation in a Vue 3 App with Vee-Validate 4 — Global Validators

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.

Global Validators

We can define our own validation rules ith the defineRule method.

For example, we can use it by writing:

<template>
  <Form @submit="onSubmit">
    <Field name="name" as="input" rules="required" />
    <ErrorMessage name="name" />
    <br />

    <Field name="email" as="input" rules="required|email" />
    <ErrorMessage name="email" />
    <br />

    <button>Submit</button>
  </Form>
</template>

<script>
import { Form, Field, ErrorMessage, defineRule } from "vee-validate";

defineRule("required", (value) => {
  if (!value || !value.length) {
    return "This field is required";
  }

  return true;
});

defineRule("email", (value) => {
  if (!value || !value.length) {
    return true;
  }

  if (!/[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}/.test(value)) {
    return "This field must be a valid email";
  }

  return true;
});

export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {},
  methods: {
    onSubmit(values) {
      alert(JSON.stringify(values, null, 2));
    },
  },
};
</script>

We call the defineRule method with the rule name.

The 2nd argument is the function we use to validate our form field.

value has the inputted value.

And we return true if the value is valid.

Otherwise, we return an error message string.

The rules prop of the Field component has the validation rules.

We combine multiple rules with the pipe.

Configuring Global Validators

We can also pass in arguments to our rules to configure it.

For example, we can write:

<template>
  <Form @submit="onSubmit">
    <Field name="name" as="input" rules="minLength:8" />
    <ErrorMessage name="name" />
    <br />

    <button>Submit</button>
  </Form>
</template>

<script>
import { Form, Field, ErrorMessage, defineRule } from "vee-validate";

defineRule("minLength", (value, [limit]) => {
  if (!value || !value.length) {
    return true;
  }

  if (value.length < limit) {
    return `This field must be at least ${limit} characters`;
  }

  return true;
});

export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {},
  methods: {
    onSubmit(values) {
      alert(JSON.stringify(values, null, 2));
    },
  },
};
</script>

We defined the minLength rule with the limit variable destructured from the array.

And then we can check against that for validation.

We set the limit variable by adding the value after the colon in the rules prop.

Multiple rules with parameters can be combined by writing:

<template>
  <Form @submit="onSubmit">
    <Field name="name" as="input" rules="required|minLength:8" />
    <ErrorMessage name="name" />
    <br />

    <button>Submit</button>
  </Form>
</template>

<script>
import { Form, Field, ErrorMessage, defineRule } from "vee-validate";

defineRule("required", (value) => {
  if (!value || !value.length) {
    return "This field is required";
  }
  return true;
});

defineRule("minLength", (value, [limit]) => {
  if (!value || !value.length) {
    return true;
  }

  if (value.length < limit) {
    return `This field must be at least ${limit} characters`;
  }

  return true;
});

export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {},
  methods: {
    onSubmit(values) {
      alert(JSON.stringify(values, null, 2));
    },
  },
};
</script>

Conclusion

We can create global validators for form fields and apply them with Vee-Validate 4 in our Vue 3 app.

Categories
Vue 3

Form Validation in a Vue 3 App with Vee-Validate 4 — Validate Nested Objects

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.

Categories
Vue 3

Form Validation in a Vue 3 App with Vee-Validate 4 — Set Form Validation Errors

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.

Initial Errors

We can initialize the form with error messages.

For example, we can write:

<template>
  <Form :initial-errors="initialErrors" :validation-schema="schema">
    <Field name="email" as="input" />
    <ErrorMessage name="email" />
    <br />

    <Field name="name" as="input" type="text" />
    <br />

    <Field name="password" as="input" type="password" />
    <ErrorMessage name="password" />
    <br />

    <button type="submit">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({
      email: yup.string().required().email(),
      name: yup.string().required(),
      password: yup.string().required().min(8),
    });

    return {
      schema,
      initialErrors: {
        email: "This email is already taken",
        password: "The password is too short",
      },
    };
  },
};
</script>

We set the initial-errors prop to the initialErrors reactive property.

It has the field names and the corresponding error messages.

Then we display them with the ErrorMessage component.

This is handy for displaying error messages retrieved from the server-side.

Setting Errors Manually

We can also set errors manually with Vee-Validate 4.

We can set the error message for one field with the setFieldError method.

And we can set error message for more than one field with the setErrors method.

For example, we can write:

<template>
  <Form v-slot="{ setFieldError, setErrors }">
    <Field name="email" as="input" />
    <ErrorMessage name="email" />
    <br />

    <Field name="password" as="input" />
    <ErrorMessage name="password" />
    <br />

    <button type="button" @click="setFieldError('email', 'nope')">
      Set Single Error
    </button>
    <button
      type="button"
      @click="setErrors({ email: 'nope', password: 'wrong' })"
    >
      Set Multiple Errors
    </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({
      email: yup.string().required().email(),
      name: yup.string().required(),
      password: yup.string().required().min(8),
    });

    return {
      schema,
    };
  },
};
</script>

to access the setFieldError and setError methods from the slot props of the Form component.

Then we call them in the click handlers of the buttons.

setFieldError takes the form field name and error message as the arguments.

And setErrors takes an object with the form field names as the keys and the error messages as the corresponding values respectively.

We can call the same methods in the submit handler.

To do this, we write:

<template>
  <Form @submit="onSubmit">
    <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, actions) {
      actions.setFieldError("email", "this email is already taken");
      actions.setErrors({
        email: "this field is already taken",
        password: "someone already has this password",
      });
    },
  },
};
</script>

We call the same methods from the actions parameter of the onSubmit submit handler.

Conclusion

We can set form validation error messages manually in our Vue 3 app with Vee-Validate 4.

Categories
Vue 3

Form Validation in a Vue 3 App with Vee-Validate 4 — Form Reset

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.

Handling Resets

We can reset the form by adding a button with the type attribute set to reset .

For example, we can write:

<template>
  <Form :validation-schema="schema">
    <Field name="email" as="input" />
    <Field name="name" as="input" type="text" />
    <Field name="password" as="input" type="password" />

    <button type="Submit">Submit</button>
    <button type="reset">Reset</button>
  </Form>
</template>

<script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
  },
  data() {
    const schema = yup.object().shape({
      email: yup.string().required().email(),
      name: yup.string().required(),
      password: yup.string().required().min(8),
    });

    return {
      schema,
    };
  },
};
</script>

When we click the Reset button, the form fields will clear.

Also, we can call the handleReset method from the slot props to do the same thing:

<template>
  <Form v-slot="{ handleReset }" :validation-schema="schema">
    <Field name="email" as="input" />
    <Field name="name" as="input" type="text" />
    <Field name="password" as="input" type="password" />

    <button type="button" @click="handleReset">Reset</button>
  </Form>
</template>

<script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
  },
  data() {
    const schema = yup.object().shape({
      email: yup.string().required().email(),
      name: yup.string().required(),
      password: yup.string().required().min(8),
    });

    return {
      schema,
    };
  },
};
</script>

Resetting Forms After Submit

We can also reset forms after submission.

For example, we can write:

<template>
  <Form @submit="onSubmit" :validation-schema="schema">
    <Field name="email" as="input" />
    <Field name="name" as="input" type="text" />
    <Field name="password" as="input" type="password" />

    <button type="submit">Submit</button>
  </Form>
</template>

<script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
  },
  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, { resetForm }) {
      console.log(values);
      resetForm();
    },
  },
};
</script>

We call the resetForm method in the submit handler to clear the form fields.

The resetForm method optionally takes an object with the values to reset to.

For instance, we can write:

<template>
  <Form @submit="onSubmit" :validation-schema="schema">
    <Field name="email" as="input" />
    <Field name="name" as="input" type="text" />
    <Field name="password" as="input" type="password" />

    <button type="submit">Submit</button>
  </Form>
</template>

<script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
  },
  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, { resetForm }) {
      console.log(values);
      resetForm({
        values: {
          email: "example@example.com",
          password: "",
        },
      });
    },
  },
};
</script>

to call resetForm with an object. The values property has an object with the form field names and corresponding values set.

We can also call resetForm from the form’s ref:

<template>
  <Form @submit="onSubmit" :validation-schema="schema" ref="form">
    <Field name="email" as="input" />
    <Field name="name" as="input" type="text" />
    <Field name="password" as="input" type="password" />

<button type="submit">Submit</button>
  </Form>
</template>

<script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
  },
  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, { resetForm }) {
      console.log(values);
      this.$refs.form.resetForm();
    },
  },
};
</script>

Conclusion

We can reset forms with the resetForm method in our Vue 3 app with Vee-Validate 4. It can be accessed in various ways.