vee-validate example

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script>
<script src="https://unpkg.com/vee-validate"></script>

<div id="app">
  <form class="ui form" @submit.prevent="onSubmit">

    <div class="repeater" v-for="(field, index) in fieldsRepeater" :key="index">
      <div class="field" :class="{error: errors.has('fname'+index)}">
        <label>First Name</label>
        <input type="text" :name="'fname'+index" placeholder="First name" v-validate="'required'" v-model="field.fname">
        <span class="error" v-if="errors.has('fname'+index)">{{errors.first('fname'+index)}}</span>
      </div>

      <div class="field" :class="{error: errors.has('lname'+index)}">
        <label>Last Name</label>
        <input type="text" :name="'lname'+index" placeholder="Last name" v-validate="'required'" v-model="field.lname">
        <span class="error" v-if="errors.has('lname'+index)">{{errors.first('lname'+index)}}</span>
      </div>

    </div>
  <button type="button" class="ui button" @click="AddField">Add Field</button>

  <button type="submit" class="ui submit button">Submit</button>
  </form>
</div>

CSS

@import url('https://unpkg.com/[email protected]/semantic.css');

span.error {
  color: #9F3A38;
}

.field {
  width: 50%;
}
.repeater {
  border: 2px solid black;
  padding: 5px;
  margin-bottom: 5px;
}

JavaScript

Vue.use(VeeValidate)

new Vue({
  el: '#app',
  data() {
    return {
      fieldsRepeater: [{
        fname: '',
        lname: '',
      }],
    }
  },
  methods: {
  	AddField() {
      this.fieldsRepeater.push({
        fname: '',
        lname: '',
      });
    },
    onSubmit() {
      this.$validator.validateAll()
      
      if (!this.errors.any()) {
        alert('submit')
      }
    }
  }
})