Add support for `ngAminate`
wmluke opened this issue · 1 comments
wmluke commented
AngularJS's new animating support is outstanding...angular-flash
should leverage it.
aminal commented
For anyone looking to incorporate ng-animate, here's what I did to accomplish it.
A few things to be aware of:
- Requires ngAnimate.
- ngAnimate will destroy your element after the ng-leave animation has been completed, so your element will never be used. Instead, a clone of your original will be dynamically created and used in its place, allowing for a single alert to be used as many times as you want. It might be better to render alert(s) by way of an ng-repeat in the instead.
- I set this up with the element being hidden by default by using BS3's
hide
class. The hide class is removed within the $animate.enter(), and added again via the $animate.leave() (prior to the element being destroyed). Because of this, you shouldn't need to use theactive-class="..."
anymore. - I make no claim that this is the "ideal" approach to implementing ngAnimate, just offer it up as a relatively simple solution that works. If you find a better way, please update accordingly.
First, in the flash-alert-directive.js
, inject $animate and add clone
and parent
var declarations:
function flashAlertDirective(flash, $animate, $timeout) {
return {
scope: true,
link: function ($scope, element, attr) {
var timeoutHandle, subscribeHandle, clone, parent;
And:
angular.module('angular-flash.flash-alert-directive', ['angular-flash.service'])
.directive('flashAlert', ['flash', '$animate', '$timeout', flashAlertDirective]);
Next, update the show()
method:
function show(message, type) {
if (timeoutHandle) {
$timeout.cancel(timeoutHandle);
}
$scope.flash.type = type;
$scope.flash.message = message;
removeAlertClasses();
angular.forEach(flash.classnames[type], function (clazz) {
// because ng-animate destroys elements, we clone & use the original element
// ignoring the original
clone = element.clone();
parent = element.parent();
// add the clone to the parent & add the alert class
parent.append(clone);
clone.addClass(clazz);
// animate the clone
$animate.enter(clone, parent, null, function() {
clone.removeClass('hide');
});
});
// this shouldn't be needed anymore
if (!isBlank(attr.activeClass)) {
element.addClass(attr.activeClass);
}
if (!message) {
$scope.hide();
return;
}
var delay = Number(attr.duration || 5000);
if (delay > 0) {
timeoutHandle = $timeout($scope.hide, delay);
}
}
Finally, update the hide()
method:
$scope.hide = function () {
$animate.leave(clone, function() {
removeAlertClasses();
clone.removeClass(attr.activeClass);
clone.addClass('hide');
});
};
Example Markup:
<div class="row">
<div class="col-md-12 col-lg-12">
<div flash-alert class="alert am-fade-and-scale hide">
<strong>You Did It!!!</strong>
<span class="alert-message">{{flash.message}}</span>
</div>
</div>
</div>
Note: I am using the angular-motion from https://github.com/mgcrea/angular-motion. You can use whatever animations you want, just replace the am-fade-and-scale
with the class name your custom animation, or the class name of the pre-defined animation you wish to use.