Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS/UI Bootstrap - fading out alert on remove

I am using Angular with UI Bootstrap. I've created the custom directive that pushes broadcasted alerst into the array of alerts that are bound to the view (rendered as Bootstrap alerts). After the certain timeout the alerts get removed from the array (and hence from the view). Here is the code:

angular.module('myApp')
  .directive('alerts', function ($timeout) {
    return {
      restrict: 'E',
      templateUrl: 'views/alerts.html',
      scope: true, /*share scope between alerts directives*/
      link: function (scope) {
        scope.alerts = [];

        scope.$on('alert', function (event, alert) {
          var newLength = scope.alerts.push({type: alert.type, msg: alert.message});

          $timeout(function() {
            scope.alerts.splice((newLength-1), 1);
          }, 3000);
        });
      }
    };
  });

I am wondering whether it is possible to add a fade out(or indeed any other animation) to the alerts prior to removing them? Any help and tips would be appreciated!

like image 343
alexs333 Avatar asked Sep 17 '13 07:09

alexs333


2 Answers

In Angular > 1.1.5

You can use angular's built-in animation feature. You basically just add a data-ng-animate="'<animation class>'" on the repeated element.

See this excelent post animation-in-angularjs or the answer from @Nikos.

In Angular 1.0.7 (stable)

is a as far as I know no animation support. However you could build the animation yourself. I'm no angular pro, so this might not be the best approach.

Create a second $timeout that adds a 'fade out CSS3' animation that kicks in before the first timeout triggers:

  1. Create CSS3 animation classes for hiding an alert (there might be already from bootstrap)

    @keyframes fadeOut
    {
      from { opacity: 1.0; }
      to { opacity: 0.0; }
    }
    
    @-webkit-keyframes fadeOut 
    {
      from { opacity: 1.0 }
      to { opacity: 0.0 }
    }
    
    .fade-out
    { 
      animation: fadeOut 2s infinite;
      -webkit-animation: fadeOut 2s infinite;
    }
    
  2. Add a 2nd $timeout:

    $timeout(function() { alert.expired = true; }, 2000);
    
  3. In your template add a conditional class with ng-class:

    <div ng-repeat="alert in alerts" ng-class="{'fade-out': alert.expired}">...</div>
    
like image 134
Stefan Avatar answered Sep 28 '22 18:09

Stefan


We have a similar setup; the template:

<div ng-controller="messages">
    <div ng-repeat="msg in messages"
        ng-animate="{enter: 'enter-slide', leave: 'leave-slide'}"
        alert type="msg.type" close="closeMsg($index)">{{msg.msg}}</div>
</div>

The controller is simple, containing the following function and the messages array:

function closeMsg(index) {
    $scope.messages[index].remove();
}

The animation definition (see ng-animate - we are using jQuery UI):

module.animation("enter-slide", function () {
    return {
        setup: function (element) {
            element.hide();
        },
        start: function (element, done, memo) {
            try{
                element.slideDown(function () {
                    done();
                });
            }
            catch(ex){}
        }
    };
});

module.animation("leave-slide", function () {
    return {
        start: function (element, done, memo) {
            element.slideUp(function () {
                done();
            });
        }
    };
});

Of course you substitute slideUp/Down() with the desired effect.

like image 37
Nikos Paraskevopoulos Avatar answered Sep 28 '22 19:09

Nikos Paraskevopoulos