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

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

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

表单输入.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() 方法。我在开发人员工具的控制台中收到此错误 2 次。

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

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

    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()
          }
        }
      }) 
    }

我做错了什么,我自己弄不明白

最佳答案

我认为发生此问题是因为位置或地址因 step === 5 条件而未出现在 html 中,您仍然尝试验证该部分。您可以输入以下条件来消除此错误===>

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

关于vue.js - 尝试使用 vee-validate 时验证不存在的字段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53250809/

相关文章:

vue.js - 调度接收未定义的值

javascript - 避免 JavaScript 中的空数组

javascript - 了解如何在 Bootstrap-vue 中使用分页

vue.js - 使用 VueJS 2 重用模态

javascript - RouterLink 属性是只读的

vue.js - 在 vue.js Web 组件目标中使用 Vuetify 版本的 Material 图标

javascript - Vue.js 项目 - CSS 模块的模块构建失败

javascript - vue js table 加新行时类似Stack Overflow的高亮效果

vue.js - 视觉 : v-model and input event in custom component derived of a custom component

javascript - 使用 Vue.js 和 Vue CLI 3 进行一些处理后通过 props 渲染项目