[Vuejs]-Optional nested validation in vuelidate

3👍

What you could do instead of asking for each subfield of engine to be required is to ask every engine to have both size and power, so that for everytime there is an engine it must have those keys. Add this together with the requiredIf and you have the following: Every vehicle must have a type, if it is a car then an engine is required and every engine must have a power and size.

The following snippet shows it working.

Vue.use(vuelidate.default);
let { required, requiredIf, helpers } = validators;
const contains = (param) =>
  (value) => !helpers.req(value) ||
    param.reduce((accum, curr) => accum && curr in value, true);
var app = new Vue({
  el: '#app',
  data: () => ({
    vehicles: [
      {
        type: 'car',
        engine: {
          size: 5,
          power: 2.5,
        }
      },
      {
        type: 'bike',
      }
    ]
  }),
  validations: {
    vehicles: {
      $each: {
        type: { required },
        engine: {
          required: requiredIf((value) => value.type === 'car'),
          contains: contains(['size', 'power']),
        }
      }
    }
  },
  created() {
    console.log(this.$v.$invalid);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuelidate@0.7.5/dist/vuelidate.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuelidate@0.7.5/dist/validators.min.js"></script>
<div id="app"></div>

1👍

I went through a similar situation recently and resolved using ‘parentVm’, as documented at https://vuelidate.js.org/#sub-accessing-component.

You should try this:

...

engine: {
  required: requiredIf((parentVm) => {return parentVm.type === 'car'}),
  size: {between: between(yourMinValue, yourMaxValue)},
  power: {between: between(yourMinValue, yourMaxValue)},
} 
...

Leave a comment