cristinafsanz
2/21/2020 - 4:00 PM

Vee-validate

Vee-validate

This library is used to validate the forms.

The validation is done:

  • In the child component when interacting with it.
  • In the parent when submitting the form.

Example:

Email validation: It is required, it should be an email and has a constraint of 1000 characters in the backend.

See components CreateOrderStep1.vue (parent) and CFormInput.vue (child) to check full code.

Parent Component

In the child component it is added:

  • The rules attribute that uses the children to validate all the rules set.
  • The ref, to access to the input and validate the child when submit the form (See isFormValid to check a possible way to do it).
<template>
    <main>
        <c-form-input
            ref="email"
            :rules="required|email|max:1000"
            ...
        />
        <c-button
            text="Next"
            @click.native="next()"
        />
    </main>
</template>

<script>
export default {
    methods: {
        async next() {
            const isFormValid = await this.isFormValid();
            if (isFormValid) {
                // Save data and go to next step
            }
        },

        async isFormValid() {
            const refs = this.$refs;
            const isValidObject = await refs.email.$children[0].validate();
            return isValidObject.valid;
        },
    }
}
</script>

Child component

The <validation-provider wraps the <input> with all the rules set from the parent. The error message is displayed via errors[0] and the input can be styled to display the error with a different border color.

The are rules that exist in the library, like email, required and max and others that can be added, like phone.

<template>
    <section class="c-form-input">
        <label :for="inputId" class="c-form-input__label">
            {{ text }}
            <span v-if="isRequired" class="mandatory">*</span>
        </label>
        <validation-provider v-slot="{ errors }" :rules="rules">
            <input
                :class="{ 'c-form-input__error-input': errors.length > 0 }"
                ...
            />
            <span class="c-form-input__error-text">
                {{ errors[0] }}
            </span>
        </validation-provider>
    </section>
</template>

<script>
import { ValidationProvider, extend } from "vee-validate";
import { required, email, max } from "vee-validate/dist/rules";
import PhoneNumber from "awesome-phonenumber";

extend("email", {
    ...email,
    message: "Email is not valid",
});

extend("required", {
    ...required,
    message: "This field is required",
});

extend("max", {
    ...max,
    message: "The field exceeds the maximum number of characters",
});

extend("phone", {
    message() {
        return "The field is not a valid phone number";
    },
    validate(value) {
        return new Promise(resolve => {
            let phone = new PhoneNumber(value);
            let phoneES = new PhoneNumber(value, "ES");
            resolve({ valid: phone.isValid() || phoneES.isValid() });
        });
    },
});

export default {
    components: {
        ValidationProvider,
    },

    props: {
        ...
        /* Rules that vee-validate uses */
        rules: {
            type: String,
            default: "",
        },
    },

    computed: {
        isRequired() {
            return this.rules.includes("required");
        },
    },
};
</script>