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

$animate.removeClass() doesn't work if addClass animation incomplete #7222

Closed
greglockwood opened this issue Apr 24, 2014 · 11 comments
Closed

Comments

@greglockwood
Copy link

Request Type: bug

How to reproduce:

  • Use $animate.addClass() to add a class to an element, e.g. 'super'
  • While the 'super-add' class has been added to the element, and before the 'super' class has been added, use $animate.removeClass() to remove the 'super' class.
  • When the jqLiteRemoveClass() function is called to remove the 'super' class, it will not be removed due to the element not having that class yet.
  • In the next tick, the 'super-add' class will be removed from the element, and the 'super' class is added, even though it was requested to be removed.

Component(s): ngAnimate, jqLite

Impact: medium

Complexity: small

Detailed Description:

The way I got this to occur was by using ng-class with the object syntax where the condition for one of the classes was initially true but then became false (possibly within the same $digest, I'm not sure). Hence the class was first added but then (unsuccessfully) removed.

I would imagine that the solution would be to check for active 'addClass' animations when trying to remove classes and if there is one for the class to be removed, cancelling it.

@matsko matsko self-assigned this May 30, 2014
@matsko
Copy link
Contributor

matsko commented May 30, 2014

Working on a fix.

@matsko matsko added this to the 1.3.0 milestone May 30, 2014
@matsko
Copy link
Contributor

matsko commented Jul 1, 2014

This should be working now in master. Can you test it out using: https://code.angularjs.org/snapshot/

If not then this should be fully fixed when: #7767 goes in later today.

@matsko
Copy link
Contributor

matsko commented Jul 1, 2014

This bug should now be fixed in master since #7767 is in.

@matsko
Copy link
Contributor

matsko commented Jul 21, 2014

@greglockwood can you please retest this out on the snapshot version: https://code.angularjs.org/snapshot/

@btford btford removed the gh: issue label Aug 20, 2014
@matsko
Copy link
Contributor

matsko commented Aug 26, 2014

This commit just did a huge fix on class based animations:
2f4437b

You can test it out on the snapshot version:
https://code.angularjs.org/snapshot/

@porjo
Copy link

porjo commented Sep 1, 2014

Not sure if related, but after upgrading from beta.19 to rc.0 I'm seeing issues with addClass not being applied with $animate. I have a spinner which shows/hides on http request using the following directive:

.directive('loadingWidget', ['requestNotification', '$animate',
           function (requestNotification, $animate) {
               return {
                   restrict: 'AC',
                   link: function (scope, element) {

                       //subscribe to listen when a request starts
                       requestNotification.subscribeOnRequestStarted(function () {
                           // show the spinner!
                           $animate.removeClass(element, 'ng-hide');
                       });

                       requestNotification.subscribeOnRequestEnded(function () {
                           // hide the spinner if there are no more pending requests
                           if (requestNotification.getRequestCount() === 0) {
                               $animate.addClass(element, 'ng-hide');
                           }
                       });
                   }
               };
           }
])

ng-hide is applied when the http request takes a long time to complete, but for short requests ng-hide never gets applied

@matsko
Copy link
Contributor

matsko commented Sep 1, 2014

With RC0 you need to run $apply inline with addClass/removeClass/setClass: 2f4437b

@porjo
Copy link

porjo commented Sep 2, 2014

Thanks - looks like I should have read the commit notes!

Using $apply() gets me "$digest already in progress" error, but $timeout() seems to work e.g.

$timeout(function(){
    $animate.addClass(element, 'ng-hide');
});

@matsko
Copy link
Contributor

matsko commented Sep 2, 2014

Don't use $timeout (since it also runs a digest).

Do this:

function safeApply(fn) {
   $scope.$$phase ? fn() : $scope.$apply(fn);
}

safeApply(function() {
   $animate.addClass(element, 'ng-hide');
});

@porjo
Copy link

porjo commented Sep 2, 2014

I've tried using safeApply however I find that ng-hide only gets applied sometimes. Adding console.log after the call to addClass confirms that it is being called in every case, however is only effective in some cases.

With $timeout I don't see this problem.

@matsko
Copy link
Contributor

matsko commented Sep 2, 2014

OK. Would you mind creating a new issue and putting up a plunkr? I can have a look tomorrow.

@jeffbcross jeffbcross modified the milestones: Backlog, 1.3.0, Purgatory Sep 29, 2014
@Narretz Narretz closed this as completed Jun 6, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants