Vee-validate: only required if fulfilled

I am using Vuejs2 and vee-validate to validate a form. This is a great package, however I am struggling to implement a conditional required field.

When a specific radio option is selected, I want two select boxes to be needed. And when this radio is not selected, I want the two select fields to be optional.

I've tried using the methods attach

and detach

. I can successfully detach the check. And I see when I attach the field that appears in the object fields

. But this is not confirmed 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>

      

+7


source to share


2 answers


Maybe you mean something like that?

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

      



Where isRequired is a calculated field that depends on a condition

+35


source


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

      



In my case, it worked by specifying the above condition. It is also useful in case of multiple validation rules ... for example 'Required | number | between: 18.99 '..

+1


source







All Articles