Animating CSS styles in Vue.js based on JavaScript triggers

Within my Vue.js application, I've implemented a login form that I'd like to shake whenever a login attempt fails.

Though I have achieved the desired shaking effect, I'm not completely satisfied with my current solution. Here's a simplified version of my code:

const Home = {
    data() {
        return {
            shakeForm: false
        }
    },
    template: `
        <div>
            <form :class="{'form-shaking': shakeForm}"
                  @submit.prevent="login"
                  @animationend="shakeForm = false;"
            >
                form fields
            </form>
        </div>
    `,
    methods: {
        async login() {
            // ...
            const rawResponse = await fetchLogin();

            if (!rawResponse.ok) {
                this.shakeForm = true;
                return;
            }

            // login successful
        }
    }
};
.form-shaking {
    position: relative;
    animation: shake-horizontally .2s ease-out 2;
}

@keyframes shake-horizontally {
    from {
        left: 0;
    }

    25% {
        left: 25px;
    }

    75% {
        left: -25px;
    }

    to {
        left: 0;
    }
}

In essence, I am toggling the shakeForm boolean property to dynamically apply and remove the form-shaking class on the <form> element when needed. The class is removed upon completion of the shaking animation to enable it to play again.

I am curious if there is a specific feature within Vue.js designed to handle situations like this. I explored transition and animation capabilities but did not come across a suitable alternative.

Answer №1

If you want to add some extra flair to your form, you can manually adjust the styles.animation attribute on the go to create a shaking effect. Here's how you can do it:

function shake() {
    document.getElementsByClassName('form-shaking')[0].style.animation = 'shake-horizontally .2s ease-out 2';
    // Stop the animation once it's done
    window.setTimeout(function() {
        document.getElementsByClassName('form-shaking')[0].style.animation = 'unset';
    }, 400);
}

(Make sure that the animation is set to unset when calling the function for it to work properly.)

For demonstration purposes, here's an example of how you could use this technique with some driver code:

function shake() {
    console.log('Incorrect Login: shaking form...')
    document.getElementsByClassName('form-shaking')[0].style.animation = 'shake-horizontally .2s ease-out 2';
    // Stop the animation once it's done
    window.setTimeout(function() {
        document.getElementsByClassName('form-shaking')[0].style.animation = 'unset';
        console.log('Incorrect Login: form shake state reset.')
    }, 400);
}

window.setTimeout(shake, 1000)
window.setTimeout(shake, 2000)
window.setTimeout(shake, 3000)
.form-shaking {
    position: relative;
    /* animation: shake-horizontally .2s ease-out 2; */
}

@keyframes shake-horizontally {
    from {
        left: 0;
    }

    25% {
        left: 25px;
    }

    75% {
        left: -25px;
    }

    to {
        left: 0;
    }
}
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
    <meta charset="utf-8">
    <title>CSS Animation on JS Event</title>
</head>

<body>
    <div class="form-shaking" style="margin: 32px; display: inline-block; background-color: black; min-width: 100px; min-height: 100px;"> </div>
</body>

</html>

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

What is your preferred datepicker for Vue.js 2?

Can anyone recommend a Vue.js 2.0 date picker component that meets my specific needs? I'm in search of one with the following requirements: Ability to select a range - start date and end date. Easily customizable using CSS. Capability to trigger a m ...

Modifying a $scope variable beyond the controller in AngularJS

I am trying to update a variable called $scope.outsidescope outside of the controller in my AngularJS application. The routing is done using $routeProvider, and the $scope.outsidescope variable is located outside of the ng-view. My query is how can I modi ...

Unable to retrieve value - angularJS

An AngularJS application has been developed to dynamically display specific values in an HTML table. The table consists of six columns, where three (Work Name, Team Name, Place Name) are fixed statically, and the remaining three columns (Service One, Servi ...

Is there a way to retrieve the width and height of a parent element within a nested declaration in SASS?

Is there a way for a child element to automatically adopt the dimensions of its parent? How can I retrieve the width and height values of the parent element in order to achieve this effect? Here is an example code snippet: .thumb { width: 120px; ...

CSS - Ignoring Padding Causes Unexpected White Space to Appear

I am encountering a simple error, and the following address will direct you to where the issue can be seen. Why is certain parts of the header appearing white instead of the light shade of green it is set to be? It should be positioned right at the top un ...

Encasing the app component with a context and encountering the issue: TypeError - (destructured parameter) does not have a defined value

My goal is to wrap all components under the app in a context to provide specific functionalities (as evidenced by my UserContext component). import React, { useState, createContext, useContext } from 'react' const Context = createContext(); exp ...

The error message "MVC JS deletethisproduct is not defined at HTMLAnchorElement.onclick (VM457 Index:40)" indicates that there

Upon clicking the button, I encounter this error: "deletethisproduct is not defined at HTMLAnchorElement.onclick" While I understand that using onclick is not the ideal approach, I am employing it because I need to retrieve the product id from the mode ...

How can we enhance the backbone sync feature by appending a query string to the URL?

I am facing an issue with adding a token to the backbone URL query string and I am seeking assistance from you all. Here are three important things to note: There is a REST API that requires a token for each request An NGINX backend handles authenticatio ...

Turn off Vuetify's v-touch functionality within a specific nested element

Currently, I am utilizing Vuetify and seeking a way to trigger certain code when the user swipes either left or right. Within my project, there is a container structured as follows: <div v-touch="{ left: () => performActionA(), right ...

The vertical spacing in Font "bottom-padding" appears to be larger than anticipated

Recently, I purchased the font Proxima Nova for my project and I am encountering issues with vertical alignment. Despite setting margins, line-heights, and padding to match those of Arial, the results are not consistent as the Proxima Nova appears misalign ...

Utilizing Radio Buttons for Table Selection in a React Application

Currently, I am utilizing React, MUI, and Formik in my project. My task involves implementing a table where only one radio button can be selected per row. How can I achieve this functionality? If you want to take a look at my code, it's available on ...

Clicking will open the link in both a new tab and the current tab

I'm looking to enable ng click functionality to work in both new tabs and the current tab. The URL is dynamically generated based on a certain condition. Here is the HTML: <a ng-href="{{myPathVariable }} " ng-click=" GoToThemes()" class="shift-l ...

Issues with Node JS app's handling of php mailer code

I've made a basic website using the Node JS framework and included a php mailer for handling the contact form. Unfortunately, I'm facing issues getting it to function properly. Could it be possible that there is an underlying problem with Node JS ...

Does Vuex have a feature similar to mapDispatchToProps in Redux for managing actions and state?

In a child component, I found myself using this.updateData() instead of this.$store.dispatch(), with the updateData function being inherited from its parent component. Does anyone know how to accomplish this? ...

Struggling to eliminate the unseen padding or white space preventing the text from wrapping under the button

Just starting out with html and css and could use some assistance with a small issue I've come across. While redesigning a website, I have a three-button form (Donate, Find, Subscribe). I'm trying to get the paragraph underneath the Donate and Fi ...

AngularJS UI-Grid not displaying JSON data

Just started learning AngularJS and everything was going smoothly until I hit a roadblock... I have been struggling to display the JSON data returned from my REST service call. While hard-coding a data array in my controller works fine, displaying the act ...

Retrieving a compilation of items found within text selected by the user on a website

Imagine a scenario in which a webpage contains the following structure: <p> <span class="1">Here's some text</span> <span class="2">that the user</span> <span class="3">could select.</span> </p> I ...

The correct way to extract a jwt token from headers and integrate it into an express application

After successfully implementing both the frontend and backend in express.js with authentication and authorization using JWT, I have confirmed that the JWT token is being properly set upon login. You can see the auth-token key in the image below: https://i ...

Step-by-Step Guide on Dividing Table Row Data into Two Distinct Tables

At present, I have created a dynamic table that retrieves data from the database using forms in Django. I'm facing an issue with this table as even though there are 7 columns, only 2 of them are visible. However, all 5 hidden columns do contain impor ...

The CSS styling of Vuetify TreeView does not support text wrapping

I'm having trouble getting the long text in this CodePen snippet to break and wrap properly. It extends off screen, rendering the append button unclickable. I've experimented with various CSS rules but haven't found a solution yet. Check ou ...