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

$animate.cancel doesn't cancel add/removeClass animation #14204

Closed
johnjesse opened this issue Mar 9, 2016 · 8 comments
Closed

$animate.cancel doesn't cancel add/removeClass animation #14204

johnjesse opened this issue Mar 9, 2016 · 8 comments

Comments

@johnjesse
Copy link

Not sure this is the right place to report this, but I found very little on $animate.cancel on the issues or stackOverflow.

I have found the $animate.cancel does not seem to work with addClass and removeClass.
see codepen
http://codepen.io/johnjwood/pen/ZWWagW

@Narretz
Copy link
Contributor

Narretz commented Mar 10, 2016

Okay, there seem to be a few problems. For one, the docs are not really clear. What's returned from $animate.addClass et al is the animation runner, not the promise. The runner has a then fn that delegates to the internal promise. When you do var animationPromise = $animate.addClass(element, 'red').then(function() { ... }) you are actually assigning the return value of the then fn (another promise) to the variable, not the runner. So you need to change that to:

var animationPromise = $animate.addClass(element, 'red')
animationPromise.then(function() { ... })

Hooowever, that still doesn't have the desired effect. I assume what you expect is that the animation stops and the final animation state is applied?

@johnjesse
Copy link
Author

Hi, thanks for getting back to me, I had been having some trouble with this elsewhere and extracted it out to a codePen and was surpised it didn't behave as described in the docs. I will change the then so it acts on the promise, but still the cancellation is annoying.

I agree with you on the desired behaviour, As the cancel is on the animation it should end the transition applying the final state.

@mafredri
Copy link

mafredri commented Apr 8, 2016

Hi, I thought I'd add that I ran into this exact same issue (with addClass/removeClass). I made the initial mistake of storing the promise, not the runner, in a variable. After fixing that I still expected that canceling the runner would reject the promise, but that doesn't seem to be the case.

@reitsma
Copy link

reitsma commented Dec 2, 2017

Hi, checking the code (1.6.4) I see that cancel will call the runner.end(). However, I think it should actually call runner.cancel() instead. The cancel will call the reject of the promise, but end() calls the resolve. The intended semantics of the runner are a bit unclear (end() vs completed() vs cancel()).

So, cancel is ending the animation after all, however not with a reject, but with a resolve of the promise. I now need to keep state myself to determine the reason for resolving.

@Narretz
Copy link
Contributor

Narretz commented Dec 4, 2017

Hi @reitsma, since you brought this up again, would like to open a PR that changes this behavior and improves on the documentation?

@gkalpak
Copy link
Member

gkalpak commented Dec 4, 2017

This has been the case since the "big ngAnimate refactor", but interestingly the initial implementation had a bug:

cancel: function(runner) {
  runner.cancel && runner.end();
}

It is not clear whether the original intention was to use runner.cancel && runner.cancel() or runner.end && runner.end(), but the former seems more likely (and makes more sense to me).

This was "fized" in a subsequent "documentation" change 😃

So, 👍 for fixing it, but sounds like a breaking change nonetheless.

@reitsma
Copy link

reitsma commented Dec 4, 2017

@Narretz Not sure what you are asking from me, but I it would indeed be helpful when this gets fixed. Although it is a breaking change, the functionality as it is now is already broken, at least for those who use the promise. Interesting analysis of @gkalpak, we had 50% chance on a correct fix...

@Narretz
Copy link
Contributor

Narretz commented Dec 7, 2017

@reitsma you could open a PR which changes the cancel method to call runner.cancel, preferrably with tests included

@Narretz Narretz modified the milestones: Ice Box, 1.7.0 Dec 8, 2017
@Narretz Narretz self-assigned this Dec 12, 2017
Narretz added a commit to Narretz/angular.js that referenced this issue Dec 20, 2017
Closes angular#14204

BREAKING CHANGE:

$animate.cancel(runner) now rejects the underlying
promise and calls the catch() handler on the runner
returned by $animate functions (enter, leave, move,
addClass, removeClass, setClass, animate).
Previously it would resolve the promise as if the animation
had ended successfully.

Example:

```js
var runner = $animate.addClass('red');
runner.then(function() { console.log('success')});
runner.catch(function() { console.log('cancelled')});

runner.cancel();
```

Pre-1.7.0, this logs 'success', 1.7.0 and later it logs 'cancelled'.
To migrate, add a catch() handler to your animation runners.
@Narretz Narretz closed this as completed in 16b82c6 Feb 2, 2018
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

5 participants