1

My template contains 2 fields called text, email. The template look as shown below

HTML

    <!DOCTYPE html>
<html>
<head>
    <title>Vue - Validations</title>
    <script src="Libraries/vue/vue.min.js"></script>
    <script src="Libraries/vue/vuelidate.min.js"></script>
    <script src="Libraries/vue/validators.min.js"></script>
</head>
<body>
<div id="app">
    <h2>Form Validation</h2>
    <input v-model="text" v-on:blur="$v.text.$touch()" :class="status($v.text)">
    <!--<p>{{!$v.text.required ? 'Text is required': !$v.text.minLength ? 'Text must be 5 characters' : '' }}</p>-->
    <p style="color:red;">{{textErrMsg}}</p>
    <input v-model="email" v-on:blur="$v.email.$touch()" :class="status($v.email)">
    <p style="color:red;">{{emailErrMsg}}</p>
  <pre>{{ $v }}</pre>
</div>
<script src="app.js"></script>
</body>
</html>

JS

Vue.use(window.vuelidate.default)
const { required, minLength,email, numeric, minValue } = window.validators
new Vue({
    el: "#app",
  data: {
    text: '',
    email: '',
    textErrMsg: '',
    emailErrMsg: ''
  },
  validations: {
    text: {
      required,
      minLength: minLength(5)
    },
    email: {
     required,
     email
    }
  },
  methods: {
    status(validation) {
        return {
        error: validation.$error,
        dirty: validation.$dirty
        
        
        // Want to perform somethins like this
         if(validation.text.required){
           this.textErrMsg == "Text is required";
         } else if(validation.text.minLength){
         this.textErrMsg == "Text must be 5 characters";
         }
         
         if(validation.email.required){
           this.emailErrMsg == "Email is required";
         } else if(validation.email.email){
         this.emailErrMsg == "Enter valid email";
         }
         
      }
    }
  }
})

As commented in the js file, I want to detect the validation fail conditions(i,e required, email, minLength...) so that i can build and show appropriate message in the template.

Instead of doing this stuff in the template.

<p>{{!$v.text.required ? 'Text is required': !$v.text.minLength ? 'Text must be 5 characters' : '' }}</p>

Fiddle link

1 Answer 1

1

I've two solutions for you. The first one is based on your Code and the key/value pairs for our inputs. The second one is based on an inputs object. In this solution I iterate over all values and thereby assemble the form.

I have added an errorMessages object instead of an error string for each value. I have updated it using vm.$set.

Vue.use(window.vuelidate.default)
const { required, minLength, email } = window.validators

// SOLUTION 1
new Vue({
  el: "#app",
  data() {
    return {
      text: '',
      email: '',
      errorMessages: {},
    }
  },
  validations: {
    text: {
      required,
      minLength: minLength(5)
    },
    email: {
      required,
      email
    }
  },
  methods: {
    status(e) {
      const name = e.target.name;
      const currentValidation = this.$v[name];

      // first of all reset
      this.$set(this.errorMessages, name, "");

      if(!currentValidation.required){
        this.$set(this.errorMessages, name, "Is required");
      } 
      if(typeof currentValidation.minLength !== 'undefined' && !currentValidation.minLength){
        this.$set(this.errorMessages, name, "Must be 5 characters");
      }

      // E-Mail check
      if(
        typeof currentValidation.email !== 'undefined' && 
        !currentValidation.email && 
        currentValidation.$invalid
      ) {
        this.$set(this.errorMessages, name, "Must be an email");
      }

    }
  }
});

// -------------------------

// SOLUTION 2
new Vue({
  el: "#app2",
  data() {
    return {
      inputs: {
        text: {
          value: '',
          title: 'Text',
          error: ''
        }, 
        email: {
          value: '',
          title: 'E-Mail',
          error: ''
        }, 
      },
      errorMessages: {},
    }
  },
  validations: {
    inputs: {
      text: {
        value: {
          required,
          minLength: minLength(5)
        }
      },
      email: {
        value: {
          required,
          email
        }
      },
    }
  },
  methods: {
    edit(e) {
      const value = e.target.value;
      const name = e.target.name;
      const currentValidation = this.$v.inputs[name].value;
      const currentInput = this.inputs[name];

      // set the value
      this.$set(currentInput, 'value', value);

      // reset
      this.$set(currentInput, 'error', '');

      // Want to perform something like this
      if(!currentValidation.required){
        this.$set(currentInput, 'error', "Is required");
      } 
      if(typeof currentValidation.minLength !== 'undefined' && !currentValidation.minLength){
        this.$set(currentInput, 'error',"Must be 5 characters");
      }


      if(
        typeof currentValidation.email !== 'undefined' && 
        !currentValidation.email && 
        currentValidation.$invalid
      ) {
        this.$set(currentInput, 'error', "Must be an email");
      }

    }
  }
})
input {
  border: 1px solid silver;
  border-radius: 4px;
  background: white;
  padding: 5px 10px;
}

.dirty {
  border-color: #5A5;
  background: #EFE;
}

.dirty:focus {
  outline-color: #8E8;
}

.error {
  border-color: red;
  background: #FDD;
}

.error:focus {
  outline-color: #F99;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/validators.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vuelidate.min.js"></script>

<div id="app">
  <h3>Form Validation</h3>
  <input 
    v-model="text" 
    name="text"
    @input="status"
    @focus="status"
    @blur="$v.text.$touch()" 
  />

  <p style="color:red;">{{errorMessages.text}}</p>

  <input 
    v-model="email" 
    name="email"
    @input="status"
    @focus="status"
    @blur="$v.email.$touch()" 
  />

  <p style="color:red;">{{errorMessages.email}}</p>
</div>

<h1>Group</h1>

<div id="app2">
  <h3>Form Validation</h3>
  
  <template v-for="(input, name) in inputs">
    {{input.title}}
    <input 
      :value="input.value"
      :name="name"
      @input="edit"
      @blur="$v[name].$touch()" 
    />

    <p style="color:red;">{{input.error}}</p>
  </template>

  
  <pre>{{ inputs }}</pre>
</div>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.