What is causing my Vue leave transition to malfunction?

Currently, I am utilizing vee validate for my form validation. Specifically, I have implemented vue transition to handle the display of validation errors in the following manner:

 <input type="text" name="name" v-validate="'required'">
<transition name="slide-fade">
  <div v-show="errors.has('name')">{{ errors.first('name') }}</div>
</transition>

For the CSS styling:

    .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;
}

My concern lies in the fact that while the transition works smoothly when an error message is entering the screen, it fails to do so when the error message disappears. What could be causing this issue?

Answer №1

The transition is in action. It may seem to disappear suddenly because there's no longer any errors.first('name') being displayed.

By adding another string alongside errors.first('name'), such as Error:, the situation becomes clearer.

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 absolutely necessary...

Take into account the added complexity of the code, but if it cannot be avoided, you must include a watcher for the value of the input and capture the first error when it occurs.

As vee-validate does not offer error listeners, this is the current workaround. Refer to the demonstration below.

Vue.use(VeeValidate);
new Vue({
  el: '#demo',
  data: {
    name: "Erase me",
    nameError: ""
  },
  watch: {
    name() {
      // Wait for at least two ticks, as vee-validate requires one tick for validation
      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 an error will appear. Type again and the error will disappear.<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>

Answer №2

While this topic may be considered old, I have come up with a simpler solution that requires minimal code. This solution is perfect for those who are still on the lookout.

The concept behind this solution involves checking for error messages every time a key is pressed in the input field using the @keypress event. The error message is then saved in a variable and displayed along with the actual error message in a div using an OR operator. This ensures that the error.message variable is never set to undefined. Even if the VeeValidate error message is not available, something will still be displayed until the animation completes.

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>

If you have multiple inputs, you can modify the solution by passing the '$event' variable in the updateError() function (changing it to updateError($event)) and handling it in the declaration. By using srcElement, you can identify the source element of the keypress event (in our case, an input) and then manipulate its respective variables (such as error.name and error.email) based on its name/class/id. The process remains straightforward.

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 trust this explanation has been beneficial to you!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ensuring Date Data Integrity with HTML5 Validations

I need to set up validation for a mobile website that includes two input fields. The first field should validate that the value is not later than today's date, while the second field should validate that it is not later than one year in advance of the ...

Verify optional chaining support in Angular app for browsers

Within my Angular application, I am looking to verify if a client's browser supports optional chaining (es2020) in order to load a library that contains both a modern ES version and a legacy one. The issue arises when the Angular compiler (which I su ...

Guide on toggling a modal in a nested component with a prop in Vue.js

Here is my current child component setup: <Edit @fetchInfo="fetchInfo" :agencyData="agency" :dialogEdit.sync="dialogEdit" ></Edit> This component essentially features a modal. Initially, the modal is hidden: data(){ r ...

Creating an Image slideShow with only one Image - making it slide on itself

Apologies for this confusing and vague question. Imagine I only have a single image, and I want to create a slideshow using technologies like Angular, jQuery, JavaScript, or just CSS. What I am aiming for is when the user clicks on my slide button, the i ...

axios.get consistently delivers a Promise of type <Pending>

I have been searching for a solution to my issue, but so far none of the suggestions have worked for me. Below is the code that I am struggling with: const Element = () => { async function getEndData() { const data = (await getEnd()) ...

The async function in Jasmine is causing issues with expectedAsync functionality

Currently conducting the following examination: it("should receive rejection", async done => { class someTest { async run(){ return this.rejectFunc(); } async rejectFunc(){ return new Promise( ...

Scrolling with Buttons in both Right and Left directions

I am working with three divs: left, middle, and right. The middle div will contain content, while the left and right divs are designated for buttons that will scroll the middle div. Specifically, I plan to display lists of pictures in the middle div. If a ...

The oddity of a lone quotation mark trying to break

var x = "Test \'" > undefined var y = "Test '" > undefined x === y > true x > "Test '" https://i.stack.imgur.com/ZrHo5.jpg Aha! Both of these strings are actually equal (as shown in the example code) - but why is that the ...

Adding a class to individual elements generated through a v-for loop: a step-by-step guide

I have been working on a basic inventory "checker" that generates 14 divs labeled as either "active" or "inactive". Using Vue, I am able to create these divs with a simple v-for loop: <div class="inventory"> <div class="item" v-for="index in 14" ...

Illuminate a corresponding regular expression within a text input

I currently have a functional code for testing regex, which highlights matching patterns. However, my challenge lies in highlighting the result within the same input as the test string. Below you will see the HTML and JavaScript snippets along with two ima ...

Manipulating HTTP responses and variables in Angular 6

I created a custom application using the MEAN stack that allows users to sign up and log in. To enhance security, I want users to reconfirm their identity by entering their password or a PIN if they return to the application after some time. To achieve th ...

Incorporating text onto an HTML webpage

Context: My program reads a file and displays it on an HTML page. The code below utilizes regex to extract errors from the file. Instead of using console.log for debugging, is there a way to display the results on the HTML page? When attempting: document ...

dividing an HTML string into individual variables using JavaScript

How can a string be split in pure JavaScript (without using JQuery/dojo/etc) in the most efficient and straightforward way? For example: var tempString = '<span id="35287845" class="smallIcon" title="time clock" style="color:blue;font-size:14px;" ...

Enabling direct access to sub-folder files within the root of npm imports

A new npm module I am creating has a specific folder structure: lib/ one-icon.jsx another-icon.jsx /* about 100 more */ package.json I would like to import these files in this manner: import OneIcon from 'icon-package/one-icon'; However ...

How can AngularJS effectively parse JSON data containing HTML elements?

We are experiencing difficulties in reading a json file containing html content. Here is the code snippet with the json data we are working with: Json data: { "aboutContent": { "listItems": [{ "title": "Investors", "de ...

Is Formik Compatible with TextareaAutosize?

I've implemented react-textarea-autosize and formik in my project, but I'm having trouble connecting the change events of formik to TextareaAutosize. Can anyone guide me on how to do this properly? <Formik initialValues={{ ...

Is jQuery Autocomplete functioning properly on outdated browsers, but not on newer ones?

Here is the JSON data I have for my auto complete feature { "list" : [ { "genericIndicatorId" : 100, "isActive" : false, "maxValue" : null, "minValue" : null, "modificationDate" : 1283904000000, "monotone" : 1, "name":"Abbau", ...

Tips for creating a new terminal window and interacting with it?

I have a node server that generates logs of activities in the terminal. To have more control over the server during runtime, I aim to integrate a repl server within it. However, I need to ensure that the logs and repl server do not interfere with each ot ...

Merge a dropdown menu with an alphabetically arranged list that is interactive with clickable options

I am still learning HTML and Javascript but I'm doing my best. Currently, I am facing a challenge where I need to create a button that, when clicked, opens a dropdown menu containing a table of data. The user should then be able to select a number fr ...

This error occurs when trying to assign a value to a property of a variable that is currently undefined

Having some issues with assigning the latitude and longitude values to a variable in my code. I am able to retrieve them correctly, but when trying to use them in another method (onUpload()), I am facing some errors. export class latlonComponent implement ...