Lead FE developer @Hypefactors
Bulgaria
Team Member
Vue
data: () => ({
form: {
name: "",
email: ""
},
dirty: false
}),
computed: {
hasErrors() {
return !(this.isNameValid && this.isEmailValid);
},
isNameValid() {
const name = this.form.name
return required(name) && min(name, 10);
},
isEmailValid() {
const email = this.form.email
return required(email) && isEmail(email);
}
},
methods: {
submit() {
this.dirty = true;
// return if errors
if (this.hasErrors) {
return false;
}
alert("Form submitted");
}
}
<div
class="px-4"
:class="{ hasError: !isNameValid && dirty }"
>
<label class="mr-2 font-bold text-grey">Name</label>
<input type="text" class="input" v-model="form.name" />
</div>
<div
class="px-4"
:class="{ hasError: !isEmailValid && dirty }"
>
<label class="mr-2 font-bold text-grey">Email</label>
<input type="email" class="input" v-model="form.email" />
</div>
import { required, email } from 'vuelidate/lib/validators'
export default {
data:()=>({
form: {
name: '',
email: ''
}
}),
validations: {
form: {
name: { required },
email: { required, email }
}
}
}
export function isNotJoe(value) {
if (!value) return true;
return !value.includes("Joe");
}
export function notGmail(value = "") {
return !value || !value.includes("gmail")
}
export function illegalChars(value) {
const charsList = ["#", "&", "$", "~"];
const regex = `[${charsList.join(",")}]`;
const regexExp = new RegExp(regex);
return !regexExp.test(value);
}
import { illegalChars, isNotJoe, notGmail } from './validators'
import { required, email } form 'vuelidate/lib/validators'
export default {
data: () => ({
form: {
name: '',
email: ''
}
}),
validations: {
form: {
name: { required, illegalChars, isNotJoe },
email: { required, email, notGmail }
}
}
}
<template>
<div
class="form-group"
:class="{ hasError: v.$error }"
>
<label class="mr-2 font-bold text-grey">
Email
</label>
<input
type="email"
class="input"
v-model="email"
placeholder="user@yahoo.com"
/>
<div class="text-sm mt-2 text-grey-darker">
Email is required and must NOT be gmail<br />
Async check if email is less than 10 chars
</div>
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ""
},
v: {
type: Object,
required: true
}
},
computed: {
email: {
get() {
return this.value;
},
set(value) {
this.v.$touch();
this.$emit("input", value);
}
}
}
};
</script>
<form @submit.prevent="submit" novalidate>
<div class="flex justify-center my-6">
<div class="px-4">
<name-component v-model="form.name" :v="$v.form.name"/>
</div>
<div class="px-4">
<email-component v-model="form.email" :v="$v.form.email"/>
</div>
</div>
<div class="text-center">
<button type="submit" class="button">
Submit
</button>
</div>
</form>
Pros
Cons
<div class="form-group" :class="{ 'hasError': v.$error }">
<label class="mr-2 font-bold text-grey">Email</label>
<input
type="email"
class="input"
v-model="email"
placeholder="user@yahoo.com"
@input="v.$touch()"
>
<div class="text-sm mt-2 text-red" v-if="v.$error">
<div v-if="!v.required">Email is required</div>
<div v-if="!v.notGmail">Email should not be a Gmail one</div>
<div v-if="!v.isEmailAvailable">Email is not available</div>
<div v-if="!v.email">Email is not a properly formatted</div>
</div>
</div>
<form-group :validator="v" label="Email">
<input
type="email"
class="input"
v-model="email"
placeholder="user@yahoo.com"
@input="v.$touch()">
</form-group>
<div class="form-group" :class="{ 'hasError': v.$error }">
<label class="mr-2 font-bold text-grey">Email</label>
<input
type="email"
class="input"
v-model="email"
placeholder="user@yahoo.com"
@input="v.$touch()"
>
<div class="text-sm mt-2 text-red" v-if="v.$error">
<div v-if="!v.required">Email is required</div>
<div v-if="!v.notGmail">Email should not be a Gmail one</div>
<div v-if="!v.isEmailAvailable">Email is not available</div>
<div v-if="!v.email">Email is not a properly formatted</div>
</div>
</div>
import VuelidateErrorExtractor, { templates } from "vuelidate-error-extractor";
Vue.use(VuelidateErrorExtractor, {
i18n: false,
// Define common validation messages.
messages: {
required: "{attribute} is required!",
isJoe: "{attribute} must be Joe",
notGmail: "{attribute} must not be gmail",
email: "{attribute} is not a valid Email address.",
isEmailAvailable:
"{attribute} is not available. Must be at least 10 characters long."
}
});
Vue.component("form-group", templates.singleErrorExtractor.foundation6);
<template>
<div class="form-group" :class="{ hasError: hasErrors, hasSuccess: isValid }">
<div class="label">
{{ label }}
</div>
<div class="control"><slot/></div>
<div class="control-helper text-red mt-4 text-sm" v-if="hasErrors">
<div v-for="error in activeErrorMessages" :key="error">{{ error }}</div>
</div>
</div>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
mixins: [singleErrorExtractorMixin]
};
</script>
errors | Object | All validation error objects for the field. Its a dynamic property so its in sync with the form field's state. |
activeErrors | Object | The currently active error objects. |
activeErrorMessages | Object | The currently active error messages. |
mergedMessages | Object | Merges both the messages prop and the globally defined ones on init. |
firstError | Object | Returns the first error object. |
firstErrorMessage | String | Returns the first active error message. |
hasErrors | Boolean | If field has any errors. |
<form-summary :validator="$v.form"/>