可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to disable my submit button until my form is filled out correctly, this is what I have so far:
<form>
<input type="text" class="form-control" v-validate="'required|email'" name="email" placeholder="Email" v-model="userCreate.userPrincipalName" />
<span v-show="errors.has('email')">{{ errors.first('email') }}</span>
<button v-if="errors.any()" disabled="disabled" class="btn btn-primary" v-on:click="sendInvite();" data-dismiss="modal" type="submit">Send Invite</button>
<button v-else="errors.any()" class="btn btn-primary" v-on:click="sendInvite();" data-dismiss="modal" type="submit">Send Invite</button>
</form>
The above only prints an error message and disables my submit button after I've started inputting a value. I need it to be disabled from the start, before I start interacting with the input, so that I cannot send an empty string.
Another question is if there is a better way than using v-if
to do this?
EDIT:
userCreate: {
customerId: null,
userPrincipalName: '',
name: 'unknown',
isAdmin: false,
isGlobalAdmin: false,
parkIds: []
}
回答1:
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
回答2:
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
回答3:
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.
回答4:
To check whether a form is invalid or not we can add a computed
property like this:
computed: {
isFormInValid() {
return Object.keys(this.fields).some(key => this.fields[key].invalid);
},
},
Now if you want to start checking immediately before user interaction with any of the fields, you can validate manually inside mounted
lifecycle hooks:
mounted() {
this.$validator.validate();
}
回答5:
or using computed
computed: {
formValidated() {
return Object.keys(this.fields).some(key => this.fields[key].validated) && Object.keys(this.fields).some(key => this.fields[key].valid);
}
}
and use
button :disabled="!formValidated" class="btn btn-primary" v-on:click="sendInvite();" data-dismiss="modal" type="submit">
回答6:
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
回答7:
For the current version 3 (As at the time of writing).
Step 1
Ensure form fields can be watched.
Step 2
Get a reference to the validator instance:
<ValidationObserver ref="validator">
.
Step 3
Trigger validation silently whenever the form fields change.
Here's an example:
export default {
data() {
return {
form: {
isValid: false,
fields: {
name: '',
phone: '',
}
}
}
},
watch: {
'form.fields': {
deep: true,
handler: function() {
this.updateFormValidity();
}
}
},
methods: {
async updateFormValidity() {
this.form.isValid = await this.$refs.validator.validate({
silent: true // Validate silently and don't cause observer errors to be updated. We only need true/false. No side effects.
});
},
}
}
<button :disabled="form.isValid">
Submit
</button>