AngularJS/UI Bootstrap - fading out alert on remove

26,585

Solution 1

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>
    

Solution 2

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.

Share:
26,585
alexs333
Author by

alexs333

Ruby forever!

Updated on July 09, 2022

Comments

  • alexs333
    alexs333 almost 2 years

    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!