Angular animate not working correctly on first run when element is initially hidden
Asked Answered
M

2

6

I am wiring up a status bar on my angular app, the purpose is when a request is made to the server the bar will show the response message, will have a background colour to denote success or error, and if it was successful to hide after a few seconds.

What I am seeing is that the first time this logic is run through after loading the page the animations are not run (both the fade in and timed fadeout fail to run), but only if the status bar element is initially hidden, if I set the ng-show variable to true on page load all the animations work as expected.

I did inspect the source via chrome's developer tools and during this first run the div has these classes alert-bar ng-hide-remove ng-hide-remove-active alert-bar-success ng-animate ng-hide after the animation should have been finished. When the animation does work the only classes present are alert-bar alert-bar-success ng-animate ng-hide.

The HTML:

<div class="alert-bar" ng-show="response.show"  ng-class="(response.result == true) ? 'alert-bar-success' : 'alert-bar-danger'">
    <div class="container">
        <label>Message: {{response.message}}</label>
    </div>
</div>

The CSS:

.alert-bar {
    width: 100%;
    margin-top: -20px;
    margin-bottom: 20px;
}

.alert-bar-success {
    background-color: #5cb85c;
    border-color: #4cae4c;
    color: #ffffff;
}

.alert-bar-danger {
    color: #ffffff;
    background-color: #d9534f;
    border-color: #d43f3a;
}

.alert-bar.ng-hide-add, .alert-bar.ng-hide-remove {
  -webkit-transition:all linear 0.3s;
  -moz-transition:all linear 0.3s;
  -o-transition:all linear 0.3s;
  transition:all linear 0.3s;
  display:block!important;
}

.alert-bar.ng-hide-add.ng-hide-add-active,
.alert-bar.ng-hide-remove {
  opacity:0;
}

.alert-bar.ng-hide-add,
.alert-bar.ng-hide-remove.ng-hide-remove-active {
  opacity:1;
}

The Controller:

controllers.controller("AppController", ['$scope', '$timeout', function($scope, $timeout) {
    $scope.response = {};

    $scope.response.received = function(message, result) {
        $scope.response.message = message;
        $scope.response.result = result;
        $scope.response.show = true;
        if (result == true) {
            $timeout(function () {
                $scope.response.show = false;
            }, 4000);
        }
    };
}]);
Mendoza answered 16/4, 2014 at 23:22 Comment(0)
P
7

This happens due to interplay between the animation code applied for both the ng-class and ng-hide directives. The only way I have made things like this work is to use separate <div> elements which are shown/hidden conditionally but that have static classes.

Here is a plunkr that demonstrates splitting the above into two <div> elements to create a working example for the problem in the question:

http://plnkr.co/edit/PFNGkOLKvs8Gx9h1T6Yk?p=preview

Alternatively, you could forego the use of ng-hide/ng-show entirely and use ng-class exclusively.

Edit: see http://plnkr.co/edit/JiLPc6cqiLHR21c64cCy?p=preview for a version that uses ng-class exclusively.

Practitioner answered 22/4, 2014 at 18:39 Comment(2)
Awesome, I can live with using 2 divs. I will award the bounty tomorrow when then lockout time is up.Mendoza
Glad to be of assistance! I went ahead and created a new plunkr which demonstrates a way that it can be achieved with a single div and ng-class without ng-hide: plnkr.co/edit/JiLPc6cqiLHR21c64cCy?p=previewPractitioner
A
1

You don't need to use two divs. I guess the simplest solution is just putting animate css into class "ng-hide-add-active" only, not into "ng-hide-add". Like below:

.page-ready-animate.ng-hide-add-active {
  -webkit-animation: 0.5s fadeOutDown;
  animation: 0.5s fadeOutDown;
}
Amuse answered 15/2, 2016 at 8:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.