简体   繁体   中英

Why my vue Leave transition not working?

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?

The 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 becomes 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.com/vue"></script> <script src="https://cdn.jsdelivr.net/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.com/vue"></script> <script src="https://cdn.jsdelivr.net/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.com/vue"></script> <script src="https://cdn.jsdelivr.net/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 (becoming 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.com/vue"></script> <script src="https://cdn.jsdelivr.net/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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM