user3800799 user3800799 - 1 year ago 48
AngularJS Question

Angular provider - $animate is not working properly

Why is this not working?

doesn't know what to 'leave', causing multiple instances of my new element. Why is that happening?


angular.module('ngNotify', [])
.provider('ngNotify', function () {

this.$get = ['$injector', '$document', '$rootScope', function ($injector, $document, $rootScope) { = function(){

var $animate;

if (!$animate) {
$animate = $injector.get('$animate');

var bodyElement = angular.element(document.querySelector('body'))
var redBlockElement = angular.element('<div class="red block"></div>')

// close previous instances

$animate.enter(redBlockElement, bodyElement).then(function() {

return this;


I load this code as a seperate JS to my main app. This is how my
file looks

var myApp = angular.module('myApp ',[
'ngNotify', // the dependency I'm trying to create




I took the variables outside
and the duplicate problem solved. But how can I make my message dynamic?

'use strict';

angular.module('ngNotify', [])
.provider('ngNotify', function () {

this.$get = ['$injector', '$document', '$timeout', '$rootScope', '$animate', function ($injector, $document, $timeout, $rootScope, $animate) {

var html = '<div class="ng-notify">' + text + '</div>'; // text has to be dynamic

var tmpl = angular.element(html);
var body = $document.find('body').eq(0);
var bodyElement = angular.element(document.querySelector('body')); = function(text){
$animate.enter(tmpl, body);

return this;


Answer Source

The problem is that each time show is called, the following code will create a new element:

var redBlockElement = angular.element('<div class="red block"></div>')

This element will not be attached to the DOM yet, so passing it to $animate.leave will not achieve anything, as there is nothing to remove.

Then the element is passed to $animate.enter and is attached to the DOM.

So each time show is called, a new element will be created and added.

One solution is to move the following lines so they are only called once:

var bodyElement = angular.element(document.querySelector('body'));
var redBlockElement = angular.element('<div class="red block">Test</div>'); = function() { ...

Then always work with the redBlockElement reference, passing it to leave, enter or change its text value.

If you want to them to be different elements each time you can either keep a reference to the previous element created and remove it before creating and adding a new one, or simply query the DOM and remove it:

var bodyElement = angular.element(document.querySelector('body')); = function() {

  var existing = angular.element(bodyElement[0].querySelector('.red.block'));


  var redBlockElement = angular.element('<div class="red block"></div>');

  $animate.enter(redBlockElement, bodyElement).then(function() {

Note that this example only removes one existing element, even if there are multiple.