securisec
securisec

Reputation: 4031

Vuetify how can I disable button till all validation rules are true?

I am using Vuetify to create a simple form where the data is being validated by some rules associated with each field. What I am trying to do is disable the Submit button if any of those validation rules fails. How can I do so? What I am trying to understand is how to check the state of each rule so that I can bind the disabled property on the button.

<template>
  <v-card>
    <v-card-text>
      <v-combobox
        v-model="addTool.name"
        :rules="rules.name"
        :items="toolNames"
        counter
        label="Name of the tool"
      ></v-combobox>
      <v-combobox
        multiple
        :small-chips="true"
        :deletable-chips="true"
        :hide-selected="true"
        :clearable="true"
        v-model="addTool.categories"
        :rules="rules.categories"
        label="Select/Add categories"
        :items="this.toolCategories"
        :search-input.sync="searchCat"
        @change="searchCat = ''"
      ></v-combobox>
      <v-text-field
        v-model="addTool.site"
        label="URL for the tool. It is best to use a Github repo link."
        :rules="rules.site"
      ></v-text-field>
    </v-card-text>
    <v-card-actions>
      <v-spacer></v-spacer>
      <v-btn @click="submit" color="grey darken-4" class="green--text text--accent-2" dark>Add</v-btn>
    </v-card-actions>
  </v-card>
</template>

<script>
export default {
  data() {
    return {
      dialog: false,
      searchCat: "",
      addToolMessage: undefined,
      addTool: {
        name: "",
        categories: [],
        created_on: "",
        site: ""
      },
      rules: {
        name: [
          v => !!v || "Required.",
          v => v.length < 80 || "Name is too long",
          v =>
            !this.toolsData
              .map(n => n.name.toLowerCase())
              .includes(v.toLowerCase()) || "This tool already exists"
        ],
        categories: [v => v.length != 0 || "At least one category is needed"],
        site: [
          v => !!v || "Required.",
          v =>
            new RegExp(
              "^(?:(?:https?|ftp)://)(?:S+(?::S*)?@)?(?:(?!(?:10|127)(?:.d{1,3}){3})(?!(?:169.254|192.168)(?:.d{1,3}){2})(?!172.(?:1[6-9]|2d|3[0-1])(?:.d{1,3}){2})(?:[1-9]d?|1dd|2[01]d|22[0-3])(?:.(?:1?d{1,2}|2[0-4]d|25[0-5])){2}(?:.(?:[1-9]d?|1dd|2[0-4]d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:.(?:[a-z\u00a1-\uffff]{2,})).?)(?::d{2,5})?(?:[/?#]S*)?$",
              "ig"
            ).test(v) || "Not a valid URL",
          v =>
            !this.toolsData.map(u => u.site).includes(v) ||
            "This tool already exists"
        ]
      }
    };
  }
};
</script>

Upvotes: 31

Views: 50394

Answers (2)

Manish
Manish

Reputation: 5213

Vuetify will track the validity of form if you wrap input elements in v-form and then attach v-model to form like this:

<v-form v-model="isFormValid">
  <!-- all input elements go here -->
</v-form>

<!-- disable if form is not valid -->
<v-btn :disabled="!isFormValid">Add</v-btn>

You also need to add isFormValid to the component's data field:

data: () => ({
  isFormValid: false,
})

You can read more here: https://vuetifyjs.com/en/components/forms

Upvotes: 61

Matheus Valenza
Matheus Valenza

Reputation: 919

You can create a computed property do to it. Lets say name and site are requireds, so:

<temlate>
  <v-btn :disabled="isAddButtonDisabled" @click="submit" color="grey darken-4" class="green--text text--accent-2" dark>Add</v-btn>
</template>
<script>
export default {
  data() {
    return {
      addTool: {
        name: "",
        categories: [],
        created_on: "",
        site: ""
      },
    };
  },
  computed: {
    isAddButtonDisabled() {
      return !(this.addTool.name || this.addTool.site);
      // means u have neither name nor site  
    },
  },
};
</script>

If you need to check if form is valid, you can do:

export default {
  computed: {
    formValid () {
      // loop over all contents of the fields object and check if they exist and valid.
      return Object.keys(this.addTool).every(field => {
        return this.addTool[field] && this.addTool[field].valid;
      });
    }
  }
}

From here: https://github.com/logaretm/vee-validate/issues/853

Upvotes: 1

Related Questions