Question

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);
        }
    };
}]);
Was it helpful?

Solution

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.

OTHER TIPS

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top