I am using vee validate for form validation. i am using vue transition on displaying validations errors like this:
<input type="text" name="name" v-validate="'required'">
<transition name="slide-fade">
<div v-show="errors.has('name')">{{ errors.first('name') }}</div>
</transition>
Css:
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active below version 2.1.8 */ {
transform: translateX(10px);
opacity: 0;
}
Now, when an error is entering the transition is working but when the error is disappearing transition is not working. why is this happening?
I am using vee validate for form validation. i am using vue transition on displaying validations errors like this:
<input type="text" name="name" v-validate="'required'">
<transition name="slide-fade">
<div v-show="errors.has('name')">{{ errors.first('name') }}</div>
</transition>
Css:
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active below version 2.1.8 */ {
transform: translateX(10px);
opacity: 0;
}
Now, when an error is entering the transition is working but when the error is disappearing transition is not working. why is this happening?
Share Improve this question asked Mar 17, 2018 at 20:48 Rakesh KohaliRakesh Kohali 2752 gold badges5 silver badges17 bronze badges2 Answers
Reset to default 4The transition is working. You see it suddenly blank because there's no errors.first('name')
to show anymore.
When you add some other string along errors.first('name')
, say Error:
, it bees clear.
Vue.use(VeeValidate);
new Vue({
el: '#demo'
})
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active below version 2.1.8 */ {
transform: translateX(10px);
opacity: 0;
}
<script src="https://unpkg./vue"></script>
<script src="https://cdn.jsdelivr/npm/vee-validate@latest/dist/vee-validate.js"></script>
<div id="demo">
Type something and then erase. And then type again.
<input type="text" name="name" v-validate="'required'">
<transition name="slide-fade">
<div v-show="errors.has('name')">Errors: {{ errors.first('name') }}</div>
</transition>
</div>
If you really must...
Consider the amount of additional code, but if you really must do it, you would have to add a watch to the input
's value and record the first error when it happens.
vee-validate does not provide listeners to erros, so this is as good as it currently gets. See demo below.
Vue.use(VeeValidate);
new Vue({
el: '#demo',
data: {
name: "Erase me",
nameError: ""
},
watch: {
name() {
// two ticks at least, because vee-validate takes one tick to validate
Vue.nextTick().then(Vue.nextTick()).then(() => {
if (this.errors.has('name')) { this.nameError = this.errors.first('name'); }
});
}
}
})
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active below version 2.1.8 */ {
transform: translateX(10px);
opacity: 0;
}
<script src="https://unpkg./vue"></script>
<script src="https://cdn.jsdelivr/npm/vee-validate@latest/dist/vee-validate.js"></script>
<div id="demo">
Erase and error will appear. Type again and error will leave.<br>
<input type="text" name="name" v-validate="'required'" v-model="name">
<transition name="slide-fade">
<div v-show="errors.has('name')">Errors: {{ nameError }}</div>
</transition>
</div>
This is kinda' an old topic, but I figured out a much more easier solution that will work with a minimal amount of code, for everybody who's still searching for one.
What this does, is checking for the error message every time you press a key in the input (the @keypress
event), saves it into a variable, which is displayed alongside the actual error message in the div, using a OR, making sure that the error.message
variable never gets undefined
. That OR guarantees that there will be something displayed, even if the actual error (the one given by VeeValidate) isn't available, up until the animation is finished.
Vue.use(VeeValidate);
new Vue({
el: '#demo',
data() {
return {
error: {
name: null,
},
}
},
methods: {
updateError() {
const message = this.errors.first('name');
if (message) { // check if message isn't undefined
this.error.name = message;
}
},
},
});
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter,
.slide-fade-leave-to {
transform: translateX(10px);
opacity: 0;
}
<script src="https://unpkg./vue"></script>
<script src="https://cdn.jsdelivr/npm/vee-validate@latest/dist/vee-validate.js"></script>
<div id="demo">
Type something and then erase. And then type again.
<input type="text" name="name" v-validate="'required'" @keypress="updateError()"><!-- added keypress event -->
<transition name="slide-fade">
<div v-show="errors.has('name')">Errors: {{ errors.first('name') || error.name }}</div><!-- OR -->
</transition>
</div>
And if you have multiple inputs you can do this: pass the '$event' variable in the updateError()
function (being updateError($event)
), and accept it in the declaration. Then, use srcElement
to get the source element that started that keypress event (in our case an input), and fetch its name/class/id/whatever; depending on that, you can modify its respective variable (in our case error.name
and error.email
). The rest is straight forward.
Vue.use(VeeValidate);
new Vue({
el: '#demo',
data() {
return {
error: {
name: null,
email: null,
},
}
},
methods: {
updateError(e) {
const input = e.srcElement.name;
const message = this.errors.first(input);
if (message) { // check if message isn't undefined
if (input === 'name') {
this.error.name = message;
} else if (input === 'email') {
this.error.email = message;
}
}
},
},
});
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 0 0 45%;
max-width: 45%;
}
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter,
.slide-fade-leave-to {
transform: translateX(10px);
opacity: 0;
}
<script src="https://unpkg./vue"></script>
<script src="https://cdn.jsdelivr/npm/vee-validate@latest/dist/vee-validate.js"></script>
<div id="demo" class="row">
<div class="col">
Type a name and then erase. And then type again.
<input type="text" name="name" v-validate="'required'" @keypress="updateError($event)">
<!-- added keypress event -->
<transition name="slide-fade">
<div v-show="errors.has('name')">Errors: {{ errors.first('name') || error.name }}</div>
<!-- OR -->
</transition>
</div>
<div class="col" style="border-left: 2px solid black; padding-left: 10px">
Type an email and then erase. And then type again.
<input type="text" name="email" v-validate="'required'" @keypress="updateError($event)">
<!-- added keypress event -->
<transition name="slide-fade">
<div v-show="errors.has('email')">Errors: {{ errors.first('email') || error.email }}</div>
<!-- OR -->
</transition>
</div>
</div>
I hope this helped you!