Search code examples
vue.jsvuetify.jsvuelidate

Using vuelidate with vuetify


I am using vuelidate with vuetify. I have some v-text-fields using the same error-messages handler.

In the handler function to show the error message, I´d like to get the fieldtext causing the error in order to use only a handler function, instead of create many similares functions.

Is there a way to do it?

<v-text-field
class="purple-input"
label="Data"
type="date"
v-model="preco_proced.data_valor1"
:error-messages="dataValorErrors"
persistent-hint
required
></v-text-field>

<v-text-field
class="purple-input"
label="Data"
type="date"
v-model="preco_proced.data_valor2"
:error-messages="dataValorErrors"
persistent-hint
required
></v-text-field>

//error-messages
dataValorErrors() {
      const errors = [];
      //here I need the correct field:data_valor1, data_valor2 .....  
      if (!this.$v.preco_proced.data_valor??????.$dirty) return errors;
      !this.$v.preco_proced.data_valor???????.required &&
        errors.push("Data é obrigatório");
      return errors;
},

Solution

  • Yes, we can do this.

    Let's say we want to validate firstName and email and the validations option is setup like:

    validations: {
      firstName: { required },
      email: { required, email },
    },
    

    and in the template we need to update v-text-field like:

    <v-text-field 
      label="First name*" 
      v-model.trim="firstName" 
      required 
      :error-messages="getErrors('firstName', $v.firstName)" 
      @blur="$v.firstName.$touch()">
    </v-text-field>
    
    <v-text-field 
      label="Email*" 
      required 
      v-model.trim="email" 
      :error-messages="getErrors('email', $v.email)" 
      @blur="$v.email.$touch()">
    </v-text-field>
    

    and now we just need to add getErrors method for the js code like:

    methods: {
      validate() {
        this.$v.$touch();
        if (this.$v.$invalid) {
          return;
        }
      },
      getErrors(name, model) {
        const errors = [];
        if (!model.$dirty) return errors;
        switch (name) {
          case "firstName":
            !model.required && errors.push("First name is required.");
            break;
          case "email":
            !model.email && errors.push("Must be valid e-mail");
            !model.required && errors.push("E-mail is required");
            break;
          default:
            break;
        }
        return errors;
      }
    }
    

    You can keep adding multiple switch cases for other text fields also, as needed. I hope this demo example will help.

    DEMO:

    Vue.use(window.vuelidate.default)
    const { required, email } = window.validators
    
    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      validations: {
        name: { required },
        email: { required, email },
      },
      data() {
        return {
          name: '',
          email: '',
        }
      },
      methods: {
        validate() {
          this.$v.$touch();
          if (this.$v.$invalid) {
            return;
          }
        },
        getErrors(name, model) {
          const errors = [];
          if (!model.$dirty) return errors;
          switch (name) {
            case "name":
              !model.required && errors.push("First name is required.");
              break;
            case "email":
              !model.email && errors.push("Must be valid e-mail");
              !model.required && errors.push("E-mail is required");
              break;
            default:
              break;
          }
          return errors;
        }
      }
    })
    <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuelidate.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/validators.min.js"></script>
    
    <div id="app">
      <v-app>
        <v-main>
          <v-container>
            <form>
              <v-text-field v-model="name" :error-messages="getErrors('name', $v.name)" :counter="10" label="Name" required @input="$v.name.$touch()" @blur="$v.name.$touch()"></v-text-field>
              <v-text-field v-model="email" :error-messages="getErrors('email', $v.email)" label="E-mail" required @input="$v.email.$touch()" @blur="$v.email.$touch()"></v-text-field>
              <v-btn class="mr-4" @click="validate">submit</v-btn>
            </form>
          </v-container>
        </v-main>
      </v-app>
    </div>