Home > Software design >  How to use v-form inside a v-for and perform validation for a specific form?
How to use v-form inside a v-for and perform validation for a specific form?

Time:05-25

I have an array of objects which I should loop through and show a form for each object's properties. The Save button is out of the for loop. In the attached sandbox, the 2nd object doesn't contain lastname. So, how do I perform validation on click of Save button only for the 2nd form? And is there any way to validate all the forms at once? Please refer to the sandbox for a better understanding.

https://codesandbox.io/s/jolly-kepler-m260fh?file=/src/components/Playground.vue

CodePudding user response:

As submit button is outside of the forms. We can perform that validation on submit event by iterating the names array and check if any value is empty and then assign a valid flag value (true/false) against each object.

Demo :

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data: () => ({
    names: [
      {
        firstName: "john",
        lastName: "doe",
        age: 40,
        valid: false
      },
      {
        firstName: "jack",
        lastName: "",
        age: 30,
        valid: false
      },
    ],
    requiredRule: [v => !!v || 'Value is required']
  }),
  methods: {
    submitForm() {
      this.names.forEach((obj, index) => {
        if (!obj.lastName) {
            obj.valid = false;
          console.log(
            `${index   1}nd form is not valid as LastName is not available`
          );
        } else {
            obj.valid = true;
        }
      });
      
      // Now you can filter out the valid form objects based on the `valid=true`
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/vuetify.min.css"/>
<div id="app">
  <v-app id="inspire">
    <v-container >
    <v-row v-for="(name, index) in names" :key="index">
      <v-form v-model="name.valid">
        <v-col cols="12">
          <v-text-field v-model="name.firstName" outlined dense solo required :rules="requiredRule" />
        </v-col>
        <v-col cols="12">
          <v-text-field v-model="name.lastName" outlined dense solo required :rules="requiredRule" />
        </v-col>
        <v-col cols="12">
          <v-text-field v-model="name.age" outlined dense solo required :rules="requiredRule" />
        </v-col>
      </v-form>
    </v-row>
    <v-btn type="submit" @click="submitForm"> Submit </v-btn>
      </v-container>
  </v-app>
</div>

CodePudding user response:

Check this codesandbox I made: https://codesandbox.io/s/stack-72356987-form-validation-example-4yv87x?file=/src/components/Playground.vue

You can validate all v-text-field at once if you move the v-form outside the for loop. All you need to do is give the form a ref value and a v-model to make use of the built in vuetify validation methods.

<template>
  <v-container >
    <v-form ref="formNames" v-model="validForm" lazy-validation>
      <v-row v-for="(name, index) in names" :key="index">
        <v-col cols="12">
          <v-text-field
            v-model="name.firstName"
            outlined
            dense
            solo
            :rules="rulesRequired"
          />
        </v-col>
        ...
      </v-row>
    </v-form>
    <v-btn type="submit" @click="submitForm" :disabled="!validForm">
      Submit
    </v-btn>
  </v-container>
</template>

Then in the submit button all you need to do is call the validate() method of the form through the $refs object. You can also disable the submit button if any of the elements in the form don't pass the validation rules using the v-model of the form to disable the submit button.

<script>
export default {
  name: "playground",
  data: () => ({
    validForm: true,
    names: [
      {
        firstName: "john",
        lastName: "doe",
        age: 40,
      },
      {
        firstName: "jack",
        lastName: "",
        age: 30,
      },
    ],
    rulesRequired: [(v) => !!v || "Required"],
  }),
  methods: {
    submitForm() {
      if (this.$refs.formNames.validate()) {
        // Form pass validation
      }
    },
  },
};
</script>
  • Related