Validate vue-select with vee-validate

7.3k Views Asked by At

I'm new to VueJS.

I'm trying to validate vue-select using vee-validate.

I've tried to validate it manually but of course its not a good approach.

So, I tried to use vuelidate but couldn't get the desired result.

Now i'm trying to use vee-validate. Validation works fine as desired

enter image description here

but the issue is v-model.

I created a global variable product, to calculate the length of array, and passed it in v-model. So that when Its empty product's value will be zero and i can return desired result from vee-validation.

Here's the .vue html part.

<ValidationObserver>
  <form @submit.prevent="add">
    <div class="row row-xs mx-0">
      <label class="col-sm-4 form-control-label">
        <span class="tx-danger">*</span> Add product(s):
      </label>
      <div class="col-sm-8 mg-t-10 mg-sm-t-0">
        <ValidationProvider rules="required" v-slot="{ errors }">
          <v-select
            name="product"
            placeholder="Add product(s)"
            :options="availableProducts" <-- here is the options array
            :reduce="name => name"
            label="name"
            @input="setSelected"
            v-model="product" <-- this calculates length and pass it to vee **extends**
          >
          </v-select>
          <div v-for="error in errors" :key="error"> {{ error }} </div>
          </ValidationProvider>
      </div>
      <!-- col-8 -->
    </div>
  </form>
</ValidationObserver>

Here's validation.js file

import { extend } from 'vee-validate';

extend('required', value => {
    console.log(value);
    return value > 0;
});

enter image description here

I don't want this product value there. I know its not a good approach as well. I can't pass whole array to v-model because then I can't push options in it. I can't pass a single option to v-model as well then I won't get desired result.

All I want to validate v-select when options array is empty. Any suggestions?

2

There are 2 best solutions below

0
On

Veevalidate doesn't validate directly on select elements. This is my workaround.

You should create a v-field "hidden" input and a visible select v-model element. The veevalidate will take place on the v-field.

Here is an example.

<v-field type="text" class="form-control disabled" name="expirationMonth" v-model="expirationMonth" :rules="isRequired" style="display:none;"></v-field>
<select v-model="expirationMonthUI" class="form-control" @click="synchExpirationMonthUI">
                                    <option value="January">January</option>
                                    <option value="February">February</option>
                                    <option value="March">March</option>
                                    <option value="April">April</option>
                                    <option value="May">May</option>
                                    <option value="June">June</option>
                                    <option value="July">July</option>
                                    <option value="August">August</option>
                                    <option value="September">September</option>
                                    <option value="October">October</option>
                                    <option value="November">November</option>
                                    <option value="December">December</option>
                                </select>
<error-message name="expirationMonth"></error-message>

Then add this to your methods to synch both together.

synchExpirationMonthUI() {
     this.expirationMonth = this.expirationMonthUI;
}
0
On

I have found a way of doing this, with the Rendering Complex Fields with Scoped Slots from the Vee-Validate documentation. And using the bindings from Vue Select, it looks something like this:

<Field name="supportType" v-slot="{ field }" v-model="supportType">
    <v-select :options="mediaTypes" label="name" :reduce="mediaType => mediaType.id" v-bind="field">
    </v-select>
</Field>

As you can see, I am using here the name, v-slot and v-model for the Field from Vee-Validate, as normal. But the v-slot is very important as it carries the information from Vue Select to Vee-Validate, or at least I think so.

On the other hand I use the options, label, reduce and v-bind from Vue Select, these I use to handle the information. So with the :options I select my dataset, with label I tell Vue Select which label to select and show from the dataset, with :reduce I tell Vue Select what will be the value of the select tag and finally use v-bind to bind the value of the select to the Vee-Validate field. So the information used on the :reduce property will be displayed on the v-model="supportType".

I tested it with a button and it worked. And I liked this way so it is not that messy and I can use the validation and other things as usual.

Hope this helps anyone.

PD: I am using Vue 3, and the latest package of both Vee-Validate and Vue Select, as of today.