Using Vee-validate to disable button until form is filled out correctly

Probably simpliest way is to use ValidationObserver slot for a form. Like this:

<ValidationObserver v-slot="{ invalid }">
  <form @submit.prevent="submit">
    <InputWithValidation rules="required" v-model="first" :error-messages="errors" />
    <InputWithValidation rules="required" v-model="second" :error-messages="errors" />
    <v-btn :disabled="invalid">Submit</v-btn>
  </form>
</ValidationObserver>

More info - Validation Observer


Another way is to make use of v-validate.initial

<input type="text" class="form-control" v-validate.initial="'required|email'" name="email" placeholder="Email" v-model="userCreate.userPrincipalName" />

This will execute the validation of the email input element after the page is loaded. And makes that your button is disabled before interacting with the input.


Setting up the button to be :disabled:"errors.any()" disables the button after validation. However, when the component first loads it will still be enabled.

Running this.$validator.validate() in the mounted() method, as @im_tsm suggests, causes the form to validate on startup and immediately show the error messages. That solution will cause the form to look pretty ugly. Also, the Object.keys(this.fields).some(key => this.fields[key].invalid); syntax is super ugly.


Instead, run the validator when the button is clicked, get the validity in the promise, and then use it in a conditional. With this solution, the form looks clean on startup but if they click the button it will show the errors and disable the button.

<button :disabled="errors.any()" v-on:click="sendInvite();">
    Send Invite
</button>
sendInvite() {
    this.$validator.validate().then(valid=> {
        if (valid) {
            ...
        }
    })
}

Validator API


One way to disable a button until all the values you need are filled, is to use a computed property that will return bool if all values are assigned or not

Example:

Create a computed property like this:

computed: {
  isComplete () {
    return this.username && this.password && this.email;
  }
}

And bind it to the html disabled attribute as:

<button :disabled='!isComplete'>Send Invite</button

This means, disable the button if !isComplete is true

Also, in your case you don't need two if/else-bound buttons. You can use just one to hide/show it based on if the form is completed or has any errors:

<button :disabled="errors.any() || !isCompleted" class="btn btn-primary" v-on:click="sendInvite();" data-dismiss="modal" type="submit">Send Invite</button>

This button will be disabled until all fields are filled and no errors are found