尝试使用vee-validate时验证不存在的字段错误

时间:2018-11-11 16:32:49

标签: vue.js vuejs2 vue-component vee-validate

我正在尝试制作多步骤表格。为此,我做了一些输入,下拉组件。

FormInput.vue

<template>
  <div class="field">
    <label class="label has-text-left"
    :for="fieldId">
      {{ labelText }} 
    </label>
    <div class="control">
      <input 
      v-model="inputValue"
      v-bind="$attrs" 
      class="input"
      :id="fieldId"
      @input="event => {$emit('input', event.target.value)}"
      :class="{'is-danger': error, 
      'is-success': !error && instance && instance!==''}" >
    </div>
    <p class="help has-text-left danger"
    v-show="error">
      {{ error }}
    </p>
  </div>
</template>

<script>
export default {
  name: 'FormInput',
  props: {
    labelText: String,
    instance: [Number, String],
    fieldId: String,
    error: String
  },
  data () {
    return {
      inputValue: null
    }
  },
  mounted () {
    this.inputValue = this.instance
  },
  $_veeValidate: {
    name () {
      this.fieldId
    },
    value () {
      this.instance
    }
  },
  watch: {
    instance: function(newValue) {
      this.inputValue = newValue
    }
  }
}
</script>

我正在以多种形式使用此FormInput组件。例如。 QuerySportsFitnessForm.vue

<div class="modal-form" v-if="step === 5">

  <FormDropdown 
  v-if="form.standard !== 'dietician'"
  labelText="What is the gender of the student??"
  v-model="form.gender"
  :options="genderArray"
  :instance="form.gender"
  ref="gender"></FormDropdown>

  <FormInput
  type="text"
  labelText="Your locality"
  v-model="form.location"
  :instance="form.location"
  fieldId="location"
  v-validate="'required'"
  name="location"
  :error="errors.first('location')"
  placeholder="eg.Heerapura"></FormInput>

  <FormInput
  type="textarea"
  labelText="Your full address"
  v-model="form.address"
  :instance="form.address"
  fieldId="address"
  v-validate="'required|min:10'"
  name="address"
  :error="errors.first('address')"
  placeholder="Enter your postal address"></FormInput>

  <FormInput
  type="textarea"
  labelText="Anything else you would like to share with us?"
  v-model="form.comment"
  :instance="form.comment"
  fieldId="comment"
  placeholder="Comment here"></FormInput>

</div>
<script>
import axios from 'axios'
import FormInput from './FormInput'
import FormDropdown from './FormDropdown'
import FormCheckbox from './FormCheckbox'

export default {
  components: {
    FormDropdown,
    FormInput,
    FormCheckbox
  },
  name: 'QuerySportsFitnessForm',
  props: {
  },
  data () {
    return {
      modalStatus: false,
      step: 1,
      progressValue: 0,
      form: {
        fees: 1000,
        category: 'Sports and Fitness',
        standard: '',
        subjects: [],
        level: '',
        type_coaching: '',
        travel: '',
        number_of_student: '',
        coaching_location: '',
        days: '',
        gender_preference: '',
        location: '',
        address: '',
        name: '',
        age: '',
        contact: '',
        email: '',
        gender: '',
        comment: ''
      },
      typeCoachingArray: [
        { value: "batch", text: "In a Batch"},
        { value: "1-on-1", text: "1-on-1 Sessions"},
        { value: "flexible", text: "Flexible to get best tutor"}
      ],
      travelArray: [
        { value: "0-1", text: "0-1 Km"},
        { value: "0-3", text: "0-3 Km"},
        { value: "0-5", text: "0-5 Km"},
        { value: "more than 5", text: "More than 5 Km"}
      ],
      coachingLocationArray: [
        { value: "at home", text: "At Home"},
        { value: "at tutor", text: "At Tutor's Location"},
        { value: "flexible", text: "Flexible to get best tutor"},
      ],
      genderPreferenceArray: [
        { value: "male", text: "Male" },
        { value: "female", text: "Female" },
        { value: "none", text: "No preference" }
      ],
      daysArray: [
        { value: "1", text: "1 day a week" },
        { value: "2", text: "2 days a week" },
        { value: "3", text: "3 days a week" },
        { value: "4", text: "4 days a week" },
        { value: "5", text: "5 days a week" },
        { value: "6", text: "6 days a week" },
        { value: "7", text: "7 days a week" }
      ],
      levelArray: [
        { value: "beginner", text: "Beginner" },
        { value: "intermediate", text: "Intermediate" },
        { value: "advanced", text: "Advanced" }
      ],
      genderArray: [
        { value: "male", text: "Male" },
        { value: "female", text: "Female" }
      ],
      numberOfStudentArray: [
        { value: "One", text: "One" },
        { value: "Two", text: "Two" },
        { value: "Three", text: "Three" },
        { value: "More than Three", text: "More than Three" },
      ],
      dieticianSubjects: [
        "Weight Loss",
        "Weight Gain",
        "Health Condition",
        "Sports Conditioning Diets"
      ],
      martialArtsSubjects: [
        "Karate",
        "Taekwondo",
        "Wing Chun",
      ],
      trainerSubjects: [
        "General Fitness",
        "Intermediate Bodybuilding",
        "Hardcore Bodybuilding"
      ],
      yogaSubjects: [
        "Power Yoga",
        "Therapeutic Yoga",
        "Yoga for Senior Citizen",
        "Pregnancy Yoga",
        "Yoga for Everyone"
      ]
    }
  },
  mounted () {
    this.form.standard = this.$route.params.standard
    if (['dietician', 'trainer', 'yoga', 'martial-arts'].indexOf(this.form.standard) !== -1) {
      this.step = 1
    }
    else {
      this.step = 2
    }
  },
  methods: {
    modalToggle() {
      this.modalStatus = !this.modalStatus
    },
    /*addToInstance method is corrosponding to checkbox component*/
    addToInstance(e) {
      if (this.form.subjects.indexOf(e) ===-1) {
        this.form.subjects.push(e)
      }
      else {
        this.form.subjects.splice(this.form.subjects.indexOf(e), 1)
      }
    },
    prev() {
      this.progressValue -= 25
      this.step--;
    },
    next() {
      if (this.step === 1) {
        this.$validator.validate('subjects', this.form.subjects)
        if (this.form.subjects.length!==0) {
          this.step++
          this.progressValue += 20
        }
      }
      else if (this.step === 2) {
        this.$refs.level.dropdownToggle()
        this.$refs.genderPreference.dropdownToggle()
        this.$refs.days.dropdownToggle()
        if (['dietician', 'trainer', 'yoga', 'zumba'].indexOf(this.form.standard) === -1) {
          if (this.form.level !== '' && this.form.days !== '') {
            this.step++
            this.progressValue += 20
          }
        }
        else if (['dietician', 'trainer', 'yoga'].indexOf(this.form.standard) !== -1) {
          if(this.form.gender_preference !== '' && this.form.days !== '') {
            this.step++
            this.progressValue +=20
          }
        }
        else if (this.form.standard === 'zumba') {
          if (this.form.days !== '') {
            this.step++
            this.progressValue += 20
          }
        }
      }
      else if (this.step === 3) {
        if (this.form.standard !== 'dietician') {
          this.$refs.typeCoaching.dropdownToggle()
        }
        if (['chess', 'skating', 'trainer', 'yoga', 'zumba'].indexOf(this.form.standard) !== -1 && this.form.type_coaching!=='batch') {
          this.$refs.coachingLocation.dropdownToggle()
        }
        if (this.form.coaching_location !== 'at home') {
          this.$refs.travel.dropdownToggle()
        }
        if (this.form.standard !== 'dietician') {
          if (this.form.type_coaching !== '') {
            if (['chess', 'skating', 'trainer', 'yoga', 'zumba'].indexOf(this.form.standard) !== -1) {
              if (this.form.type_coaching !== 'batch' && this.form.coaching_location !=='') {
                if (this.form.coaching_location !== 'at home' && this.form.travel !== '') {
                  this.step++
                  this.progressValue += 20
                }
                else if (this.form.coaching_location === 'at home' && this.form.travel === '') {
                  this.step++
                  this.progressValue += 20
                }
              }
              else if (this.form.type_coaching === 'batch' && this.form.travel !== '') {
                this.step++
                this.progressValue += 20
              }
            }
            else if (['chess', 'skating', 'trainer', 'yoga', 'zumba'].indexOf(this.form.standard) === -1) {
              if (this.form.travel !== '') {
                this.step++
                this.progressValue += 20
              }
            }
          }
        }
        else if (this.form.standard === 'dietician') {
          if (this.form.coaching_location !== 'at home' && this.form.travel !== '') {
            this.step++
            this.progressValue += 20
          }
          else if (this.form.coaching_location === 'at home' && this.form.travel === '') {
            this.step++
            this.progressValue += 20
          }
        }
      }
      else if (this.step === 4) {
        this.$validator.validate('name', this.form.name)
        this.$validator.validate('contact', this.form.contact)
        this.$validator.validate('email', this.form.email)
        this.$validator.validate('age', this.form.age).then(() => {
          if (this.errors.items.length === 0) {
            this.step++
            this.progressValue += 20
          }
        })
      }
    },
    //Problem with this block I think
    validateBeforeSubmit() {
      this.$refs.gender.dropdownToggle()
      this.$validator.validate('location', this.form.location)
      this.$validator.validate('address', this.form.address)
      if (this.form.standard === 'dietician') {
        if (this.errors.items.length === 0) {
          this.addQuery()
          this.modalToggle()
        }
      }
      else if (this.form.standard !== 'dietician') {
        if (this.errors.items.length === 0 && this.form.gender !== '') {
          this.addQuery()
          this.modalToggle()
        }
      }
    },
    emptyCoachingLocation() {
      this.form.coaching_location = ''
    },
    emptyTravel() {
      this.form.travel = ''
    },
    addQuery() {
      axios({
        method: 'post',
        url: 'http://127.0.0.1:8000/api/hobby-query/',
        data: {
          fees: this.form.fees,
          category: this.form.category,
          standard: this.form.standard,
          subjects: this.form.subjects,
          level: this.form.level,
          type_coaching: this.form.type_coaching,
          travel: this.form.travel,
          number_of_student: this.form.number_of_student,
          coaching_location: this.form.coaching_location,
          days: parseInt(this.form.days),
          gender_preference: this.form.gender_preference,
          location: this.form.location,
          address: this.form.address,
          name: this.form.name,
          age: parseInt(this.form.age),
          contact: this.form.contact,
          email: this.form.email,
          student_gender: this.form.gender,
          comment: this.form.comment
        }
      }).then(() => { 

        this.form.subjects = [],
        this.form.level = '',
        this.form.type_coaching = '',
        this.form.travel = '',
        this.form.number_of_student = '',
        this.form.coaching_location = '',
        this.form.days = '',
        this.form.gender_preference = '',
        this.form.location = '',
        this.form.address = '',
        this.form.name = '',
        this.form.age = '',
        this.form.contact = '',
        this.form.email = '',
        this.form.gender = '',
        this.form.comment = ''

      })
      .catch((error) => {
        console.log(error);
      });
    }
  }
}
</script>

例如,我仅包括一个div。当我单击“下一步”按钮时,next()可以正常工作。当我单击提交按钮时,它会启动validateBeforeSubmit()方法。而且我在开发人员工具控制台中两次收到此错误。

Uncaught (in promise) Error: [vee-validate] Validating a non-existent field: "". Use "attach()" first.
    at createError (vee-validate.esm.js?00d1:297)
    at Validator._handleFieldNotFound (vee-validate.esm.js?00d1:2282)
    at Validator.validate (vee-validate.esm.js?00d1:1959)
    at ScopedValidator.validate (vee-validate.esm.js?00d1:3276)
    at VueComponent.validateBeforeSubmit (QuerySportsFitnessForm.vue?cb73:448)
    at invoker (vue.esm.js?efeb:2027)
    at HTMLButtonElement.fn._withTask.fn._withTask (vue.esm.js?efeb:1826)
createError @   vee-validate.esm.js?00d1:297
_handleFieldNotFound    @   vee-validate.esm.js?00d1:2282
validate    @   vee-validate.esm.js?00d1:1959
validate    @   vee-validate.esm.js?00d1:3276
validateBeforeSubmit    @   QuerySportsFitnessForm.vue?cb73:448
invoker @   vue.esm.js?efeb:2027
fn._withTask.fn._withTask   @   vue.esm.js?efeb:1826

我也尝试在validate方法调用后给出.then承诺,但是它没有改变任何东西。像这样

    validateBeforeSubmit() {
      this.$refs.gender.dropdownToggle()
      this.$validator.validate('location', this.form.location)
      this.$validator.validate('address', this.form.address).then(() {
        if (this.form.standard === 'dietician') {
          if (this.errors.items.length === 0) {
            this.addQuery()
            this.modalToggle()
          }
        }
        else if (this.form.standard !== 'dietician') {
          if (this.errors.items.length === 0 && this.form.gender !== '') {
            this.addQuery()
            this.modalToggle()
          }
        }
      }) 
    }

我在做什么错,我自己无法弄清楚

2 个答案:

答案 0 :(得分:2)

我认为正在发生此问题,因为由于step === 5的情况,html中没有位置或地址,并且您仍然尝试验证该部分。您可以将以下条件消除此错误===>

if (this.$validator.fields.find({ name: 'location' })) {
            this.$validator.validate('location');
}

答案 1 :(得分:1)

问题似乎是清除变量时触发了输入的验证值更改侦听器,该变量随后尝试验证输入,但是输入不再位于验证器的字段列表中,因为输入在其移出时已分离被隐藏了。

Feature: Login test

  Background:
    # Authorise via api
    * def login = callonce read('classpath:common/headers/admin-headers.feature')
    * def uiCookie = { name: 'SESSION', value: '#(login.userAuthInfo.authSession)', domain: 'test.internal.mysite.com' }
    * configure driver = { type: 'chrome', cookie: '#(uiCookie)' }

  Scenario: Test login
    Given driver 'https://test.internal.mysite.com/names'

此代码将解决问题。