首页 > 解决方案 > 从 vue 验证器构建自定义错误消息

问题描述

我的模板包含 2 个字段,称为textemail。模板如下图所示

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";
         }
         
      }
    }
  }
})

如 js 文件中所述,我想检测验证失败条件(即要求、电子邮件、minLength ...),以便我可以在模板中构建和显示适当的消息。

而不是在模板中做这些事情。

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

小提琴链接

标签: javascriptvue.jsvalidationvue-validator

解决方案


我有两个解决方案给你。第一个基于您的代码和我们输入的键/值对。第二个是基于一个inputs对象。在这个解决方案中,我遍历所有值,从而组装表单。

errorMessages为每个值添加了一个对象而不是一个错误字符串。我已经使用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/vuelidate@0.7.5/dist/validators.min.js"></script>
<script src="https://unpkg.com/vuelidate@0.7.5/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>


推荐阅读