Issues getting dynamic validations working in Vuelidate

Hi there.

I am using the vuelidate library for form validation, and I am dynamically setting the form fields and the validation rules depending on certain criteria from user input. The dynamic form fields each have a human readable label and a unique value (used as the key name). I pass my component a prop object containing an array of the fields to create the form and validation rules for e.g.:

    {
      'label': 'Access Token',
      'value': 'accessToken'
    },
    {
      'label': 'Folder Path',
      'value': 'folderPath'
    }
  ]

I add these fields in beforeMount() so they exist in data() and then create the dynamic validations rules in the validation() function, which gets called after beforeMount is called (so it should all be working as far as I can tell).
As soon as vm.$v.formData.$touch() has been called once to validate the form, the validation $invalid $error etc flags for each field never get updated again, despite whether the form has now come being valid or invalid.

Has anyone else run into this issue / and found a solution?

Thanks very much in advance.

My component looks like this:

<template>
  <form>
    <div class="columns is-centered" v-for="field in platform.fields" :key="field.value">
      <div class="column has-text-left is-three-quarters">
        <div class="field">
          <label class="label">{{field.label}}</label>
          <div class="control  has-icons-right">
            <input
                  class="input" :class="{'is-danger': $v.formData[field.value].$error }"
                  v-model="formData[field.value]"
                  @input="$v.formData[field.value].$touch()" :name="field.value"
                  type="text"
                  :placeholder="field.label">
                <span class="icon is-small is-right" v-if="$v.formData[field.value].$error && !$v.formData[field.value].required">
                  <i class="fa fa-warning"></i>
                </span>
          </div>
          <p class="help is-danger" v-if="$v.formData[field.value].$error">
            <span v-if="!$v.formData[field.value].required">The {{field.label}} is required!</span>
          </p>
        </div>
      </div>
    </div>
    <button type="button" class="button is-primary is-medium is-capitalized" @click="validateForm()">
      <span>Connect Your Account</span>
      <span class="icon">
        <i class="el-icon-arrow-right"></i>
      </span>
    </button>
  </form>
</template>


<script>
import { required } from 'vuelidate/lib/validators'
export default {
  name: 'my-dynamic-validation-form',
  props: {
    platform: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      formData: {}
    }
  },
  validations() {
    const vm = this
    const validations = {
      formData: {}
    }
    vm.platform.fields.forEach(function(field) {
      validations.formData[field.value] = {
        required: required
      }
    })
    return validations
  },
  methods: {
    validateForm() {
      const vm = this
      vm.$v.formData.$touch()
      const isValid = !vm.$v.formData.$invalid
      console.log('Form valid?', isValid)
    }
  },
  beforeMount() {
    const vm = this
    // Before mount, add the fields to my formData object in data()
    vm.platform.fields.forEach(function(field) {
      vm.formData[field.value] = null
    })
  }
}
</script>

I realize this is a very late answer. However, I encountered the exact same problem today, so I thought maybe I could save someone else from a lot of pain and frustration in the future.

The issue here is actually the limitations of Vue’s reactivity system. When adding the form fields to data() in beforeMount(), we need to manually set the new properties’ reactivity by using vm.$set() like so:

 beforeMount() {
   const vm = this
   // Before mount, add the fields to my formData object in data()
   vm.platform.fields.forEach(function(field) {
     vm.$set(vm.formData, field.value, null)
   })
 }