Vuetify v-text-field : how to set success status automatically from rules - vuetify.js

When I manually set the success prop on v-text-field, it turns green.
Is there anyway to get it to turn green automatically from just passing the rules?
<v-form ref="form" v-model="valid" lazy-validation>
<v-text-field
v-model="name"
:rules="nameRules"
:counter="10"
label="Name"
required
></v-text-field>
</v-form>
new Vue({
el: '#app',
data: () => ({
valid: true,
name: '',
nameRules: [
v => !!v || 'Name is required',
v => (v && v.length <= 10) || 'Name must be less than 10 characters'
]
})
https://codepen.io/damianhelme/pen/OaepbX

Related

Is there any option to have one common vuetify rule for two text fields

I have to fill either text-field-1 or text-field-2 or both In a form and I should be able to proceed with save
I tried having a flag variable but I that results in clicking on text-field-1 or text-field-2 to activate the save button
You can use computed property according to your need here is the basic example
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
valid: true,
firstName: '',
lastName: '',
nameRule: [
v => !!v || 'Name is required',
v => (v && v.length <= 10) || 'Name must be less than 10 characters',
],
}),
computed: {
nameRules () {
if(this.firstName.length == 0 && this.lastName.length == 0){
return this.nameRule;
}
if(this.firstName.length > 0 || this.lastName.length > 0 ){
return [];
}
},
},
methods: {
validate () {
this.$refs.form.validate()
},
reset () {
this.$refs.form.reset()
},
resetValidation () {
this.$refs.form.resetValidation()
},
},
})
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<v-form
ref="form"
v-model="valid"
lazy-validation
>
<v-text-field
v-model="firstName"
:counter="10"
:rules="nameRules"
label="First name"
></v-text-field>
<v-text-field
v-model="lastName"
:counter="10"
:rules="nameRules"
label="Last name"
></v-text-field>
<v-btn
:disabled="!valid"
color="success"
class="mr-4"
#click="validate"
>
Validate
</v-btn>
<v-btn
color="error"
class="mr-4"
#click="reset"
>
Reset Form
</v-btn>
<v-btn
color="warning"
#click="resetValidation"
>
Reset Validation
</v-btn>
</v-form>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>

How to extract a <form> element from Vuetify's <v-form> component

I have a Vuetify form with a ref, like this
<v-form ref="form" method="post" #submit.prevent="handleSubmit">
Onto it I attached a default-preventing submit handler whose method is as follows:
window.fetch(`${this.$store.state.apiServer}/some-url`, {
method: 'post',
body: new FormData(this.$refs.form)
}).then(response => {
// Do stuff with the response
}).catch(() => {
// HCF
});
The problem is new FormData() only accepts a pure HTML <form> element, while this.$refs.form is a VueComponent. Is there a way I can grab the <form> from inside a <v-form>?
You can get the form element using this.$refs.form.$el
Here is the working codepen: https://codepen.io/chansv/pen/OJJOXPd?editors=1010
<div id="app">
<v-app id="inspire">
<v-form
ref="form"
v-model="valid"
lazy-validation
>
<v-text-field
v-model="name"
:counter="10"
:rules="nameRules"
label="Name"
required
></v-text-field>
<v-text-field
v-model="email"
:rules="emailRules"
label="E-mail"
required
></v-text-field>
<v-btn type="submit" #click="formSubmit">submit</v-btn>
</v-form>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
valid: true,
name: '',
nameRules: [
v => !!v || 'Name is required',
v => (v && v.length <= 10) || 'Name must be less than 10 characters',
],
email: '',
emailRules: [
v => !!v || 'E-mail is required',
v => /.+#.+\..+/.test(v) || 'E-mail must be valid',
],
}),
methods: {
formSubmit() {
console.log(this.$refs.form.$el);
}
},
})

How to add custom validation which calls an API in vuetify forms?

I am trying to add custom validation to a form to test for duplicate entry.
How can I do it using only vuetify validation. I want to show a inline error message if the user input is duplicate.
Yes you can validate the name from customer input with api call and throw error to user, if the name already exist or duplicate name found
You can use rules property in vuetify text fields, it takes an array of functions and expect true(validation true, in your case name not exists) or string(if valdation false, name exists in db)
Here is the working codepen: https://codepen.io/chansv/pen/eYYdPzQ?editors=1010
<div id="app">
<v-app id="inspire">
<v-form
ref="form"
v-model="valid"
>
<v-text-field
v-model="name"
:counter="10"
:rules="[checkDuplicate, rules.required]"
label="Name"
required
></v-text-field>
<v-btn #click="submitbtn">submit</v-btn>
</v-form>
</v-row>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
valid:true,
name: '',
rules: {
required: v => !!v || 'this field is required',
}
}),
methods: {
checkDuplicate(val) {
// write your api call and return the below statement if it already exist
if (val == 'test') {
return `Name "${val}" already exist`;
} else {
return true;
}
},
submitbtn() {
this.$refs.form.validate();
},
},
})

How to add password matching validation in vuetify?

I am trying to create a profile form which have two fields
password and rePassword. basically, Both of them should be the same.
I tried using different codes found on the web and different approaches. Some of them worked but. It did'nt actually fit in with the code.
Here is the piece of code:
Profile.vue:
<v-layout>
<v-flex xs12 sm6>
<v-text-field
v-model="password"
:append-icon="show ? 'visibility' : 'visibility_off'"
:rules="[rules.required, rules.min]"
:type="show ? 'text' : 'password'"
name="password"
label="Enter Password"
hint="At least 8 characters"
counter
#click:append="show = !show"
></v-text-field>
</v-flex>
<v-flex xs12 sm6>
<v-text-field
v-model="rePassword"
:append-icon="show1 ? 'visibility' : 'visibility_off'"
:rules="[rules.required, rules.min]"
:type="show1 ? 'text' : 'password'"
name="input-10-1"
label="Re-enter Password"
hint="At least 8 characters"
counter
#click:append="show1 = !show1"
></v-text-field>
</v-flex>
</v-layout>
This is how the script looks like:
Profile.vue (script):
data() {
return {
show: false,
show1: false,
password: 'Password',
rePassword: 'Password',
rules: {
required: value => !!value || 'Required.',
min: v => v.length >= 8 || 'Min 8 characters',
emailMatch: () => ('The email and password you entered don\'t match')
},
emailRules: [
v => !!v || 'E-mail is required',
v => /.+#.+/.test(v) || 'E-mail must be valid'
],
date: new Date().toISOString().substr(0, 10),
menu: false,
items: ['male', 'female'],
address: '',
title: "Image Upload",
dialog: false,
imageName: '',
imageUrl: '',
imageFile: ''
}
},
methods: {
pickFile() {
this.$refs.image.click()
},
onFilePicked(e) {
const files = e.target.files
if(files[0] !== undefined) {
this.imageName = files[0].name
if(this.imageName.lastIndexOf('.') <= 0) {
return
}
const fr = new FileReader ()
fr.readAsDataURL(files[0])
fr.addEventListener('load', () => {
this.imageUrl = fr.result
this.imageFile = files[0] // this is an image file that can be sent to server...
})
} else {
this.imageName = ''
this.imageFile = ''
this.imageUrl = ''
}
},
}
,
validate() {
if (this.$refs.form.validate()) {
this.snackbar = true
}
},
reset() {
this.$refs.form.reset()
}
How do I add a password matching feature in the validation using vuetify.
Thanks
You can define custom rules:
computed: {
passwordConfirmationRule() {
return () => (this.password === this.rePassword) || 'Password must match'
}
}
and use it
<v-flex xs12 sm6>
<v-text-field
v-model="rePassword"
:append-icon="show1 ? 'visibility' : 'visibility_off'"
:rules="[rules.required, rules.min, passwordConfirmationRule]"
:type="show1 ? 'text' : 'password'"
name="input-10-1"
label="Re-enter Password"
hint="At least 8 characters"
counter
#click:append="show1 = !show1"
/>
</v-flex>
very easiest way is
using v-model (password and confirm_password), no need to use computation
Rule
:rules="[v => !!v || 'field is required']"
Or
:rules="[(password!="") || 'field is required']"
in password
<v-text-field label="Password*" v-model="password" type="password" required :rules="[v => !!v || 'field is required']"></v-text-field>
confirm password field
Rule
:rules="[(password === confirm_password) || 'Password must match']"
code:
<v-text-field label="Confirm Password*" v-model="confirm_password" type="password" required :rules="[(password === confirm_password) || 'Password must match']"></v-text-field>
VeeValidate is great for form validation but in my opinion is overkill for resolving this question when it can be achieved in Vuetify alone.
Following on from #ittus answer, you need to remove the arrow function in passwordConfirmationRule to access this:
return this.password === this.rePassword || "Password must match";
See this codesandbox working example (also now using Vuetify 2.x)
Very simply using Vee-validate:
<div id="app">
<v-app id="inspire">
<form>
<v-text-field
ref="password"
type="password"
v-model="pass"
v-validate="'required'"
:error-messages="errors.collect('pass')"
label="Pass"
data-vv-name="pass"
required
></v-text-field>
<v-text-field
v-model="pass2"
type="password"
v-validate="'required|confirmed:password'"
:error-messages="errors.collect('pass2')"
label="Pass 2"
data-vv-name="pass"
required
></v-text-field>
<v-btn #click="submit">submit</v-btn>
<v-btn #click="clear">clear</v-btn>
</form>
</v-app>
</div>
Vue.use(VeeValidate)
new Vue({
el: '#app',
$_veeValidate: {
validator: 'new'
},
data: () => ({
pass: '',
pass2: "",
}),
methods: {
submit () {
this.$validator.validateAll()
.then(result => {
console.log(result)
})
},
clear () {
this.pass = ''
this.pass2 = ''
}
}
})
Remember to install vee-validate first and restart your local-server.
link to codepen
link to docs
This works right for me!
// template
<v-text-field v-model="password" label="password"></v-text-field>
<v-text-field v-model="confirmPassword" :rules="confirmPasswordRules" label="confirmPassword"></v-text-field>
// script
computed: {
confirmPasswordRules() {
const rules = [(this.password === this.confirmPassword) || "Password must match."];
return rules;
},
}
This is not a clean solution definitely, but works fine.
<v-text-field
type="password"
v-model="password"
:rules="passwordRules"
required
></v-text-field>
<v-text-field
type="password"
v-model="passwordConfirm"
:rules="passwordConfirmRules"
required
></v-text-field>
let globalPassword = "";
watch: {
password() {
globalPassword = this.password;
},
},
passwordConfirmRules = [
(v) => v === globalPassword || "Password must match",
];

Vuetify Form Validation - defining ES6 rules for matching inputs

I have a (Vuetify) form with an email input that uses ES6 & regex to check if it's a valid email. How would I set up another emailConfirmationRules ruleset to check if the emailConfirmation input matches the email input?
<template>
<v-form v-model="valid">
<v-text-field label="Email Address"
v-model="email"
:rules="emailRules"
required></v-text-field>
<v-text-field label="Confirm Email Address"
v-model="emailConfirmation"
:rules="emailConfirmationRules"
required></v-text-field>
</v-form>
<template>
export default {
data () {
return {
valid: false,
email: '',
emailConfirmation: '',
emailRules: [
(v) => !!v || 'E-mail is required',
(v) => /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mail must be valid'
],
emailConfirmationRules: [
(v) => !!v || 'Confirmation E-mail is required',
] (v) => ??? || 'Confirmation E-mail does not match'
}
}
Rules are not the proper way of handling field confirmation.
emailConfirmationRules are triggered only when emailConfirmation changes, but if you change email again, your fields won't match anymore without any break of rules.
You have to handle this manually:
methods: {
emailMatchError () {
return (this.email === this.emailConfirmation) ? '' : 'Email must match'
}
}
<v-text-field v-model='emailConfirmation' :error-messages='emailMatchError()'></v-text-field>
There may be an alternative way of doing this with vee-validate too.
You can accomplish the same with a computed rule.
computed: {
emailConfirmationRules() {
return [
() => (this.email === this.emailToMatch) || 'E-mail must match',
v => !!v || 'Confirmation E-mail is required'
];
},
}
emailConfirmationRules: [
(v) => !!v || 'Confirmation E-mail is required',
(v) => v == this.email || 'E-mail must match'
],
<template>
<v-text-field
v-model="employee.email"
:rules="emailRules"
required
validate-on-blur
/>
</template>
<script>
data() {
return {
emailRules: [
v => !!v || "E-mail is required",
v =>
/^\w+([.-]?\w+)*#\w+([.-]?\w+)*(\.\w{2,3})+$/.test(v) ||
"E-mail must be valid"
],
}
</script>
Check this post
https://stackoverflow.com/a/58883995/9169379
<template>
<v-input v-model="firstPassword" />
<v-input :rules=[rules.equals(firstPassword)] v-model="secondPassword" />
</template>
<script>
data() {
firstPassword: '',
secondPassword: '',
rules: {
equals(otherFieldValue) {
return v => v === otherFieldValue || 'Not equals';
}
}
}
</script>

Resources