_Note_: for support questions, please use one of these channels: https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#question. This repository's issues are reserved for feature requests and bug reports.
Do you want to request a _feature_ or report a _bug_?
bug
What is the current behavior?
If you inject angular-animate into your application (even if you don't use it) and you switch routes, elements within those routes are not destroyed. If you are using flexbox this causes sizing issues when you come back to the original route.
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://plnkr.co or similar (template: http://plnkr.co/edit/tpl:yBpEi4).
http://plnkr.co/edit/dyBH1Szo3lIEWajKqXWj?p=preview
What is the expected behavior?
You will see that leaflet maps flexes to take up the remaining space not taken by the navbar. If you click the About link in the navbar and then click the Map route you will notice the map only renders for about half the view.
I have noticed 2 things:
What is the motivation / use case for changing the behavior?
Frameworks like leaflet that look at initial size of an element to layout children render wrong.
Which versions of Angular, and which browser / OS are affected by this issue? Did this work in previous versions of Angular? Please also test with the latest stable and snapshot (https://code.angularjs.org/snapshot/) versions.
At least 1.3.15 - 1.5.3.
Other information (e.g. stacktraces, related issues, suggestions how to fix)
Not sure, does anyone know why injecting angular-animate would cause elements in previous routes to not get destroyed?
When you say, the map doesn't get destroyed, what do you mean by that? When I switch the the about route, the content of the home route is nowhere to be found in the DOM.
As for why ngAnimate changes the behavior, I am not sure.
Add a console log in the about controller that grabs the #map div and checks its height. You will be able to grab that div and see that its height is 1/2 of what it was.
app.controller('aboutController', function($scope, $document) {
$scope.message = 'About page';
var element = $document.find('#map');
console.log('map height in about route: ' + element[0].offsetHeight);
});
Which is weird because from the about page the #map element should not be around. Then when you nav back to the map the #map div is still 1/2 of what is should be for a moment. And that 'moment' is exactly when leaflet is trying to figure out how big to make the map.
If you remove the ngAnimation injection from the app, you will not be able to access the #map div from the about controller. Which is what I would expect.
Ah, I see. It's probably because ngAnimate adds a slight delay to the removal process. Even when you have no animations, ngAnimate changes the behavior of the events a bit (because it needs to figure out if an animation is present). You can see that the map element gets removed eventually by putting the log in the about route inside a setTimeout.
You can use setTimeout or requestAnimationFrame inside the map directive too, and the map will render correctly.
Seems like a harmful side effect of ngAnimate.
Can the docs be updated to reflect this as well as suggest a setTimeout in certain cases like this?
In addition is there a way to 'fix' this side effect of ngAnimate? Adding setTimeouts in all directives/controllers that might rely on initial size being incorrect is troublesome.
It's a pretty rare case, and I wouldn't want to put something in the docs without knowing where the problem is exactly.
In addition is there a way to 'fix' this side effect of ngAnimate?
If you're not actually animating most elements, you can restrict ngAnimate to only look at elements with a certain class name. We usually use ng-will-animate.
$animateProvider.classNameFilter(/ng-will-animate/);
@dpogue Thanks, that is a perfectly valid solution!
I had another look at this, and I just like to clarify that the duplicate element is not actually a bug. When ngAnimate animates ngView, both old and new instance of ngView exist at the same time, so that you can have fancy animations. Now if you have an element with an id in your view, then you cannot guarantee that you get the right element if you search from the document. At the very least, you should search from the directive's element (or in this case, use the element directly as it is the map element).
That doesn't solve the problem, but it makes it clear where it's not coming from ;)
I'm closing this as "works as expected"
This same issue came up for us... took a while to track it down, but ngAnimate was causing flex heights to break on certain screens.
Using $animateProvider.classNameFilter(/ng-will-animate/); finally fixed the issue. Would be nice if there was more documentation on this.
Most helpful comment
If you're not actually animating most elements, you can restrict ngAnimate to only look at elements with a certain class name. We usually use
ng-will-animate.