Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vee-validate: Required only if a condition is met

I'm using Vuejs2 and vee-validate for form validation. It's a great package, however I'm struggling to implement a conditional required field.

When a particular radio option is selected, I want two select fields to be required. And when that radio is not selected, I want the two select fields to be optional.

I've tried using the attach and detach methods. I can successfully detach the validation. And I can see when I attach a field it appears in the fields object. But it's not picked up by the validator.

Here is my code:

<template>
  <form class="ui form" role="form" method="POST" action="/activate" v-on:submit.prevent="onSubmit" :class="{ 'error': errors.any() }">
    <div class="ui segment">
      <h4 class="ui header">Basic Company Information</h4>
      <div class="ui message">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
      </div>
      <div class="field" :class="{ 'error': errors.has('name') }">
        <div class="ui labeled input">
          <label class="ui label" for="name">
            Company
          </label>
          <input id="name" type="text" name="name" v-validate="'required'" v-model="name">
        </div>
      </div>
      <div class="ui error message" v-show="errors.has('name')">
        <p>{{ errors.first('name') }}</p>
      </div>
      <div class="grouped fields" :class="{ 'error': errors.has('organisation_type_id') }">
        <label for="organisation_type_id">Organisation type</label>
        <div class="field">
          <div class="ui radio checkbox">
            <input class="hidden" type="radio" name="organisation_type_id" value="1" data-vv-as="organisation type" v-validate="'required'" v-model="organisation_type">
            <label>Buyer</label>
          </div>
        </div>
        <div class="field">
          <div class="ui radio checkbox">
            <input class="hidden" type="radio" name="organisation_type_id" value="2" checked>
            <label>Seller</label>
          </div>
        </div>
      </div>
      <div class="ui error message" v-show="errors.has('organisation_type_id')">
        <p>{{ errors.first('organisation_type_id') }}</p>
      </div>
      <div v-show="organisation_type == '2'">
        <div class="field" :class="{ 'error': errors.has('countries[]') }">
          <label for="countries">Countries</label>
          <select class="ui fluid search dropdown" id="countries" name="countries[]" multiple data-vv-as="countries" v-validate="'required'">
            <option v-for="country in countries" :value="country.value">{{ country.text }}</option>
          </select>
        </div>
        <div class="ui error message" v-show="errors.has('countries[]')">
          <p>{{ errors.first('countries[]') }}</p>
        </div>
        <div class="ui message field-description">
          <p>Select all the countries you export to.</p>
        </div>
        <div class="field" :class="{ 'error': errors.has('ciphers[]') }">
          <label for="ciphers">Ciphers</label>
          <select class="ui fluid search dropdown" id="ciphers" name="ciphers[]" multiple data-vv-as="ciphers" v-validate="'required'">
            <option v-for="cipher in ciphers" :value="cipher.value">{{ cipher.text }}</option>
          </select>
        </div>
        <div class="ui error message" v-show="errors.has('ciphers[]')">
          <p>{{ errors.first('ciphers[]') }}</p>
        </div>
        <div class="ui message field-description">
          <p>Select all the ciphers you support.</p>
        </div>
      </div> <!-- End organisation_type_id -->
      <button class="ui fluid green button" type="submit">Continue</button>
    </div> <!-- .ui.segment -->
  </form>
</template>

<script>
  export default {
    props: ['countriesJson', 'ciphersJson'],
    data() {
      return {
        name: null,
        organisation_type: '2',
        countries: [],
        ciphers: [],
      }
    },
    watch: {
      organisation_type: function(value) {
        var vm = this
        if (value == '2') {
          vm.$validator.attach('countries[]', 'required');
          const select = document.getElementById('countries');
          select.addEventListener('change', function() {
            vm.$validator.validate('required', this.value);
          });
          vm.$validator.attach('ciphers[]', 'required');
          const select = document.getElementById('ciphers');
          select.addEventListener('change', function() {
            vm.$validator.validate('required', this.value);
          });
        } else {
          vm.$validator.detach('countries[]')
          vm.$validator.detach('ciphers[]')
        }
      },
    },
    mounted() {
      this.countries = JSON.parse(this.countriesJson)
      this.ciphers = JSON.parse(this.ciphersJson)
    },
    methods: {
      onSubmit: function(e) {
        this.$validator.validateAll().then(success => {
          e.target.submit()
        }).catch(() => {
          return
        })
      }
    }
  }
</script>
like image 702
Thom Vincent Avatar asked Mar 26 '17 03:03

Thom Vincent


People also ask

How do you use V validation?

All you need is to add the v-validate directive to the input you wish to validate and make sure your input has a name attribute for error messages generation. Then, pass to the directive a rules string which contains a list of validation rules separated by a pipe ' | '.

What is vee validate?

VeeValidate is a validation library for Vue. js. It has plenty of validation rules out of the box and support for custom ones as well. It is template based so it is similar and familiar with the HTML5 validation API. You can validate HTML5 inputs as well as custom Vue components.

What is data VV?

data-vv-name. Specifies a name for the field, used in components validation and as a fallback name for inputs.


2 Answers

May be you mean something like this?

<input id="name"
       type="text"
       name="name"
       v-validate="{ required: this.isRequired }"
       v-model="name">

Where "isRequired" is computed field, which depend from condition

like image 161
Pizza eu Avatar answered Nov 07 '22 05:11

Pizza eu


<input id="name"
       type="text"
       name="name"
       v-validate=" isRequired ? 'required' : '' "
       v-model="name">

In my case it worked by giving above condition.. Also it is helpful in case of multiple validation rules... e.g. 'required|integer|between:18,99'..

Adding {} will break the expression

like image 43
Shridhar Sagari Avatar answered Nov 07 '22 03:11

Shridhar Sagari