2
\$\begingroup\$

I have the code below which is working as expected. It is doing a form validation with Vue.js and Vee-Validate. It is checking that at least one checkbox is checked.

I only don't like that I have to manually call validate for oneChecked-Validator on form submission. With-out the call it's not validating on submit.

It would be great if someone could review my code and give me an advice to the following points:

  • How can I configure Vee Validator so that it evaluates the oneChecked validator with the call of this.$validator.validateAll();?

  • Is it possible to pass the this.options array into validate method of oneChecked validator? (Would be more re-usable. I've tried passing as array with JSON.stringify but couldn't get it to work.)

If there is more to improve please let me know. I'm using Vee-Validate for the first time.

You can also find the same code at jsfiddle.

const Checkboxes = {
  template: '#checkboxTmpl',
  data() {
    return {
      text: '',
      options: [{
        id: 0,
        checked: false
      }, {
        id: 1,
        checked: false
      }, {
        id: 2,
        checked: false
      }]
    };
  },
  created() {
    this.$validator.extend('oneChecked', {
      getMessage: field => 'At least one ' + field + ' needs to be checked.',
      validate: (value, [testProp]) => {
        const options = this.options;
        // console.log('questions', value, testProp, options.some((option) => option[testProp]));
        return value || options.some((option) => option[testProp]);
      }
    });
  },
  methods: {
    validateBeforeSubmit(e) {
      this.$validator.validateAll(); // why is oneChecked not validated here? --> manually trigger validate below
      this.options.forEach((option) => {
        this.$validator.validate('check0', option.checked, ['checked'])
      });

      console.log('validator', this.errors);
      if (!this.errors.any()) {
        alert('succesfully submitted!');
      }
    }
  }
};

Vue.use(VeeValidate);

const app = new Vue({
  el: '#app',
  render: (h) => h(Checkboxes)
})
<script src="https://cdn.jsdelivr.net/vee-validate/2.0.0-beta.18/vee-validate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.js"></script>

<div id="app">

</div>

<script id="checkboxTmpl" type="text/template">
  <form @submit.prevent="validateBeforeSubmit">
    <input v-model="text" name="text" v-validate.initial="text" data-vv-rules="required|min:3" placeholder="required input" />
    <p v-show="errors.has('text')">{{ errors.first('text') }}</p>
    <br/>

    <label v-for="(option, index) in options">
      <input type="checkbox" v-model="option.checked" name="check0" v-validate.initial="option.checked" data-vv-rules="oneChecked:checked" data-vv-as="checkbox" />Checkbox {{index}}
    </label>
    <p v-show="errors.has('check0')">{{ errors.first('check0') }}</p>
    <pre>{{options}}</pre>
    <button type="submit">Submit</button>
  </form>
</script>

\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

How can I configure Vee Validator so that it evaluates the oneChecked validator with the call of this.$validator.validateAll();?

Yes, you can use validateAll(), you're just not passing the fields for it to validate. Here's an example on how to do this:

methods: {
  validateBeforeSubmit(e) {
    this.$validator.validateAll({
      name0: true
    });
    console.log('validator', this.errors);
    if (!this.errors.any()) {
      alert('succesfully submitted!');
    }
  }
}

Taken from here.

Is it possible to pass the this.options array into validate method of oneChecked validator? (Would be more re-usable. I've tried passing as array with JSON.stringify but couldn't get it to work.)

Why pass it as a parameter when it's already a constant?

Consider this:

created() {
  this.$validator.extend('oneChecked', {
    getMessage: field => 'At least one ' + field + ' needs to be checked.',
    validate: (value, [testProp]) => {
      return value || Checkboxes.data().options.some((option) => option[testProp]);
    }
  });
},

This also provides you some protection for when data().options inevitably has more than 3 elements in it.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for your answer. The way with validateAll to pass a reference name was new for me and it simplifies code because I can create a map for all checkbox groups and pass it to validateAll. That's easier than calling validate with all parameters. But it breaks the validation of text input - not sure why (see this fiddle). Also what does the true mean inside the passed object? I had to pass false to make the validation work. In my demo it's working by accessing the constant but I'd like to have it more flexible. (that's OK now -see fiddle) \$\endgroup\$ Commented Jan 15, 2017 at 17:18
  • \$\begingroup\$ @AWolf I have the same problem like u, and I think I am missing some information. I asked my question on github: github.com/baianat/vee-validate/issues/1674 Maybe you can share some insights on the questions I asked there: Most important: why is my rule not validated anyway? Why do we need something like your validateBeforeSubmit. Thank you in advance. \$\endgroup\$ Commented Oct 24, 2018 at 23:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.