Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix($animate): abort class-based animations if the element is removed during digest #8958

Closed
wants to merge 1 commit into from

Conversation

matsko
Copy link
Contributor

@matsko matsko commented Sep 5, 2014

Prior to this fix, if the element is removed before the digest kicks off then it leads
to an error when a class based animation is run. This fix ensures that the animation will
not run at all if the element does not have a parent element.

Closes #8796

@petebacondarwin
Copy link
Contributor

LGTM
What is the performance cost of doing this; especially the isMatchingElement method call?

@matsko
Copy link
Contributor Author

matsko commented Sep 5, 2014

It should be constant since there is only one element within the jqLite/jQuery wrapper for both the element and $rootElement: https://github.com/angular/angular.js/blob/master/src/ngAnimate/animate.js#L404

@petebacondarwin petebacondarwin modified the milestones: 1.3.0-rc.2, 1.3.0-rc.1 Sep 7, 2014
@@ -1015,6 +1015,15 @@ angular.module('ngAnimate', ['ng'])
}

return cache.promise = runAnimationPostDigest(function(done) {
var parentElement;
if (!isMatchingElement(element, $rootElement)) { //$rootElement's parent is not inside of the app
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comment is likely incorrect. it should be element's parent is not inside of the app

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

        //any ancestor elements past $rootElement's are not apart of the app

@jeffbcross jeffbcross modified the milestones: 1.3.0-rc.1, 1.3.0-rc.2 Sep 9, 2014
@allegrem
Copy link

I had a similar issue to #8796, but the fix you provided was not enough in my case. The issue was happening in a ngRepeat directive, and I had to check also if the parentElement had the property $$NG_REMOVED (apparently added when an element was not removed yet because of pending animation).

Here is the piece of code to achieve that:

if (!parentElement || parentElement.length === 0 || parentElement[0]['$$NG_REMOVED'])

Do you need me to try to reproduce this bug in a plunkr?

@demsey2
Copy link

demsey2 commented Sep 23, 2014

is anyone looking at this issue? One unit test failed but it isn't related to this fix.

@demsey2
Copy link

demsey2 commented Sep 24, 2014

I have got the same problem and your fix is not enough. In my example I use ngTable and I managed to replicate this issue here http://plnkr.co/edit/9Ff6VJBzyyOVKYf3ZlA6 If I try to generate my columns by using ngRepeat the issue is gone. It looks like some elements are created later and the cache object attached to them exist. I excluded jQuery.

@matsko
Copy link
Contributor Author

matsko commented Oct 3, 2014

@allegrem @demsey2 this addition should solve the ngRepeat issues:

            if (!isMatchingElement(element, $rootElement)) {
              parentElement = extractElementNode(element.parent());
              if (!parentElement || parentElement['$$NG_REMOVED']) {
                done();
                return;
              }
            }

Thsnk @allegrem for the tip!

… during digest

Prior to this fix, if the element is removed before the digest kicks off then it leads
to an error when a class based animation is run. This fix ensures that the animation will
not run at all if the element does not have a parent element.

Closes angular#8796
@matsko matsko force-pushed the fix_empty_animate_parent branch from 38915e2 to 6744cbd Compare October 3, 2014 12:44
@matsko
Copy link
Contributor Author

matsko commented Oct 3, 2014

@demsey2 I can confirm that the changes in my local angular-animate.js file (which was packaged together from the code in this commit) fixes your plunkr issue.


//any ancestor elements past $rootElement's are not apart of the
//app therefore there is no need to examine the parent element
if (!isMatchingElement(element, $rootElement)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite get this check. it's not like we are traversing up until the $rootElement (even though the comment above makes it sounds like it).

@IgorMinar
Copy link
Contributor

otherwise lgtm

@demsey2
Copy link

demsey2 commented Oct 7, 2014

thanks @matsko for the fix, I tried with the plunkr example and the issue still exists. I have included a new version of ngAnimate with your fix and I can still see that error
http://plnkr.co/edit/eWHt03tSf6AowKZ61hob?p=preview

for some reasons the "$$NG_REMOVED" in elementNode doesn't exists so an animation can't be completed/done

@matsko
Copy link
Contributor Author

matsko commented Oct 7, 2014

@demsey2 looks like it's fixed on master: http://plnkr.co/edit/GFqCAzaVPezmzCcOhCC6?p=preview

@matsko
Copy link
Contributor Author

matsko commented Oct 7, 2014

@demsey2 this issue touches another problem and it's fixed with this PR. Your issue on the other hand, while similar, is caused by ngModel. It looks like the snapshot version (the next version of 1.3 RC) fixes it so we should be OK. However if it doesn't then please open a new issue.

@matsko matsko closed this Oct 7, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ngAnimate short circuts Dom removal during remove, causing off by one errors (ng339 error)
8 participants