最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to use Vuelidate to show errors only when user is finished with input - Stack Overflow

programmeradmin1浏览0评论

I have the following form built with Bootstrap-Vue, which has a bit of Vuelidation code applied to it.

<b-form @submit.prevent="onSubmit">
      <input type="hidden" name="_token" :value="csrf" />
      <transition-group name="fade">
        <b-form-select
          :class="{ 'hasError': $v.form.dobDate.$error }"
          class="mb-3"
          name="dobDate"
          id="dobDate"
          v-model.lazy="$v.form.dobDate.$model"
          :options="optionsDays"
          v-if="isSixteen"
          key="dobDateSelect"
        >
          <template slot="first">
            <option value disabled>Please select a date</option>
          </template>
        </b-form-select>
      </transition-group>
      <transition-group name="fade">
        <b-form-select
          :class="{ 'hasError': $v.form.dobMonth.$error }"
          class="mb-3"
          name="dobMonth"
          id="dobMonth"
          v-model.lazy="$v.form.dobMonth.$model"
          :options="optionsMonths"
          v-if="isSixteen"
          value="optionsMonths.key"
          key="dobMonthSelect"
        >
          <template slot="first">
            <option value disabled>Please select a Month</option>
          </template>
        </b-form-select>
      </transition-group>

      <b-alert
        show
        variant="danger"
        class="error"
        v-if="!$v.form.dobYear.required"
      >This field is required</b-alert>

      <b-alert
        show
        variant="danger"
        class="error"
        v-if="!$v.form.dobYear.minLength"
      >Field must have at least {{ $v.form.dobYear.$params.minLength.min }} characters.</b-alert>

      <b-alert class="error" v-if="!$v.form.dobYear.numeric">Please enter a valid year of birth</b-alert>

      <b-alert show variant="danger" v-if="belowSixteen">You are underage</b-alert>

      <b-form-input
        :class="{ 'hasError': $v.form.dobYear.$error }"
        placeholder="Year of Birth"
        v-model="form.dobYear"
        @blur="$v.form.dobYear.$touch()"
        autofocus
        class="form-control mb-3"
        name="year"
        id="year"
        maxlength="4"
        @keyup="checkAge"
      ></b-form-input>

      <b-button
        class="btn btn-lg btn-primary btn-block"
        type="submit"
        variant="primary"
        :disabled="$v.$invalid||belowSixteen"
      >Submit</b-button>
      <b-alert
        show
        variant="danger"
        v-if="belowSixteen"
        class="error mt-3"
      >Sorry you have to be over 16 to play</b-alert>
    </b-form>

But currently I am getting immediate feedback when the page loads which can be jarring for the user. Instead I want the errors to show when the user has finished with the input/select.

I have tried using @blur="$v.form.dobYear.$touch()" however it doesn't seem to work at all. What am I doing wrong?

Here is a snipper of how my validations look like in my script currently:

validations: {
    form: {
      dobYear: {
        required,
        minLength: minLength(4),
        maxLength: maxLength(4),
        numeric
      },
      dobMonth: {
        required: requiredIf(function() {
          return this.isSixteen;
        })
      },
      dobDate: {
        required: requiredIf(function() {
          return this.isSixteen;
        })
      }
    }
  }

I have the following form built with Bootstrap-Vue, which has a bit of Vuelidation code applied to it.

<b-form @submit.prevent="onSubmit">
      <input type="hidden" name="_token" :value="csrf" />
      <transition-group name="fade">
        <b-form-select
          :class="{ 'hasError': $v.form.dobDate.$error }"
          class="mb-3"
          name="dobDate"
          id="dobDate"
          v-model.lazy="$v.form.dobDate.$model"
          :options="optionsDays"
          v-if="isSixteen"
          key="dobDateSelect"
        >
          <template slot="first">
            <option value disabled>Please select a date</option>
          </template>
        </b-form-select>
      </transition-group>
      <transition-group name="fade">
        <b-form-select
          :class="{ 'hasError': $v.form.dobMonth.$error }"
          class="mb-3"
          name="dobMonth"
          id="dobMonth"
          v-model.lazy="$v.form.dobMonth.$model"
          :options="optionsMonths"
          v-if="isSixteen"
          value="optionsMonths.key"
          key="dobMonthSelect"
        >
          <template slot="first">
            <option value disabled>Please select a Month</option>
          </template>
        </b-form-select>
      </transition-group>

      <b-alert
        show
        variant="danger"
        class="error"
        v-if="!$v.form.dobYear.required"
      >This field is required</b-alert>

      <b-alert
        show
        variant="danger"
        class="error"
        v-if="!$v.form.dobYear.minLength"
      >Field must have at least {{ $v.form.dobYear.$params.minLength.min }} characters.</b-alert>

      <b-alert class="error" v-if="!$v.form.dobYear.numeric">Please enter a valid year of birth</b-alert>

      <b-alert show variant="danger" v-if="belowSixteen">You are underage</b-alert>

      <b-form-input
        :class="{ 'hasError': $v.form.dobYear.$error }"
        placeholder="Year of Birth"
        v-model="form.dobYear"
        @blur="$v.form.dobYear.$touch()"
        autofocus
        class="form-control mb-3"
        name="year"
        id="year"
        maxlength="4"
        @keyup="checkAge"
      ></b-form-input>

      <b-button
        class="btn btn-lg btn-primary btn-block"
        type="submit"
        variant="primary"
        :disabled="$v.$invalid||belowSixteen"
      >Submit</b-button>
      <b-alert
        show
        variant="danger"
        v-if="belowSixteen"
        class="error mt-3"
      >Sorry you have to be over 16 to play</b-alert>
    </b-form>

But currently I am getting immediate feedback when the page loads which can be jarring for the user. Instead I want the errors to show when the user has finished with the input/select.

I have tried using @blur="$v.form.dobYear.$touch()" however it doesn't seem to work at all. What am I doing wrong?

Here is a snipper of how my validations look like in my script currently:

validations: {
    form: {
      dobYear: {
        required,
        minLength: minLength(4),
        maxLength: maxLength(4),
        numeric
      },
      dobMonth: {
        required: requiredIf(function() {
          return this.isSixteen;
        })
      },
      dobDate: {
        required: requiredIf(function() {
          return this.isSixteen;
        })
      }
    }
  }
Share Improve this question asked Sep 4, 2019 at 10:08 ImranRImranR 5163 gold badges13 silver badges31 bronze badges 6
  • Have you tried to use a @click-Function on your submit-Button? It only get's triggered when the user finished his input and you could simply set your code: this.$v.form.dobYear.$touch() in there. – Matthias Commented Sep 4, 2019 at 20:58
  • Or listen for the @submit event on the form – Troy Morehouse Commented Sep 4, 2019 at 21:44
  • 1 Have you solved this issue? Please add an answer with your solution. I'm struggling with this right now... – mattelacchiato Commented Jul 15, 2020 at 13:57
  • @mattelacchiato sorry it's been a while since I used vuelidate. I briefly remember using $touch() like the first example in the ments...essentially what I did was put a few seconds delay before the validation message is shown. This gives the user some time to finish typing. Otherwise the only other option I could think of at the time was to trigger only when the submit button is clicked on but that doesn't feel so 'reactive'. – ImranR Commented Jul 16, 2020 at 14:32
  • @mattelacchiato I just took a look at the old source code I used. So it looks like I used the delayTouch method for Vuelidate, and I waited 15000 mili seconds for user input to end. See the example on the vuelidate website, just search for 'delaytouch' vuelidate.js/#sub-delayed-validation-errors – ImranR Commented Jul 16, 2020 at 14:35
 |  Show 1 more ment

2 Answers 2

Reset to default 1

Calling $touch() in blur event is right. But you could use little bit different logic with state attribute given from bootstrap-vue. You could find more detail from here Form input [contextual states]

eg:

<b-form-input
  v-model="form.name"
  type="text"
  @blur="$v.form.name.$touch()"
  :state="$v.form.name.$dirty ? !$v.form.name.$anyError : null"
/>
<b-form-invalid-feedback :state="$v.form.name.$dirty ? !$v.form.name.$anyError : null" >
  Some kind of invalid feedback Message here
</b-form-invalid-feedback>


And out of curiosity why you use v-model with validation model like shown below.

v-model.lazy="$v.form.dobMonth.$model"

Isn't it just okay for use v-model with data() like shown below?

v-model.lazy="form.dobMonth"

You can wrap it as follows:

<div v-if="$v.email.$dirty"> 
<b-alert
    show
    variant="danger"
    class="error"
    v-if="!$v.form.dobYear.required"
>This field is required</b-alert>

<b-alert
    show
    variant="danger"
    class="error"
    v-if="!$v.form.dobYear.minLength"
>Field must have at least {{ $v.form.dobYear.$params.minLength.min }} characters.</b-alert>

<b-alert class="error" v-if="!$v.form.dobYear.numeric">Please enter a valid year of birth</b-alert>

<b-alert show variant="danger" v-if="belowSixteen">You are underage</b-alert></div>

Know more

发布评论

评论列表(0)

  1. 暂无评论