How to trigger an angularjs animation from a controller method?

后端 未结 3 1227
野的像风
野的像风 2021-01-20 19:42

I would like to trigger an angular animation from a controller method.

I have come up with something that I am not satisfied with (see code below).

The issu

相关标签:
3条回答
  • 2021-01-20 19:59

    You will have another problem your animation isn't reset after the first fail, so consecutive fails won't execute the animation again. I'm afraid that there is no way to do this using pure CSS.

    What you should do first is to use the validation services provided by Angular and then separate the logic of the error animation.

    Here is the working solution, with the Prefix util factory working just fine.

    • First check form.$invalid inside your signin(formCtrl) function, if the form is $invalid or the response from the service returns a login error, then call a function which will handle the animation.

      $scope.signin = function(form){
        if(form.$invalid){
          $scope.animateError();
        }
      };
    

    • Change the CSS to only add the animation timing function and duration. So when the showAnimationError function is called it will take the form element, and add the style animationName/ webkitAnimationName with the value shake.

    Also remember to add a event listener for the animation end, so you can clean this style, for consecutive calls on showAnimationError

    /* css */
    .shake {
        -webkit-animation-duration: 400ms;
        -webkit-animation-timing-function: ease-in-out;
        animation-duration: 400ms;
        animation-timing-function: ease-in-out;
    }
    

    $scope.animateError = function(){
      if(!resetAnimationHandler){
        addResetAnimationHandler();
      }
      myForm.style[prefixUtil.animationName] = 'shake';
    };
    

    I hope this helps you

    0 讨论(0)
  • 2021-01-20 20:03

    Here is the solution I ended up using (see code below). It is an adaptation of Liamnes's proposed solution.

    angular.module('signin')
        .controller('SigninCtrl', ['$scope', '$rootScope', '$cookies', '$state', '$animate', 'signinService', function ($scope, $rootScope, $cookies, $state, $animate, signinService) {
    
            var setPersonalInfo = function (param) {
                return signinService.setPersonalInfo(param.headers, $rootScope);
            };
            var goToDashboard = function (memberType) {
                $state.go('dashboard', {memberType: memberType});
            };
            var reportProblem = function () {
                $scope.formCtrl.username.$setValidity('username.wrong', false);
                $scope.formCtrl.password.$setValidity('password.wrong', false);
                $scope.$broadcast('SIGNIN_ERROR');
            };
            var resetForm = function(formCtrl){
                formCtrl.username.$setValidity('username.wrong', true);
                formCtrl.password.$setValidity('password.wrong', true);
            };
    
            $scope.signin = function (formCtrl) {
    
                resetForm(formCtrl);
    
                if (formCtrl.$valid) {
                    signinService.signin($scope.credentials).then(setPersonalInfo).then(goToDashboard).catch(reportProblem);
                }
                else {
                    $scope.$broadcast('SIGNIN_ERROR');
                }
            }
        }])
        .directive('shakeThat', ['$animate', function ($animate) {
            return {
                require: '^form',
                scope: {
                    signin: '&'
                },
                link: function (scope, element, attrs, form) {
                    scope.$on('SIGNIN_ERROR', function () {
                        $animate.addClass(element, 'shake').then(function () {
                            $animate.removeClass(element, 'shake');
                        });
                    });
                }
            };
        }]);
    

    HTML:

    <form shake-that name="formCtrl" ng-submit="signin(formCtrl)" novalidate>
    
    0 讨论(0)
  • 2021-01-20 20:11

    I'd suggest you wrap the form in a directive, and trigger the animation via an event. e.g. in the controller you would do:

    $scope.$broadcast('FORM_ERROR');
    

    and in the directive, do something more like

    scope.$on('FORM_ERROR', function() { // code to trigger animation goes here });
    

    Makes sense to handle this as an event for me, because then it has a strict lifecycle; event is dispatched, event gets handled. A scope variable would hang around, even though it no longer has any meaning. You might even need code to 'reset' it back to its original state so the animation can be triggered again, which adds unneeded complexity.

    0 讨论(0)
提交回复
热议问题