Search code examples
angularjsng-animateangular-promise

Angularjs $animate promises css keyframe animations


According to the angular docs (emphasis mine):

With AngularJS 1.3, each of the animation methods, on the $animate service, return a promise when called. The promise itself is then resolved once the animation has completed itself, has been cancelled or has been skipped due to animations being disabled.

Whilst $animate is returning a promise, it seems to resolve instantly.

To demonstrate, I've created a simple example in codepen

Here is the relevant script (on click):

$elem = angular.element('<div class="donkey">Not resolved</div>')

$animate.enter($elem, element).then(
  $elem.html('My promise is resolved!') 
)

And style:

.donkey
  &.ng-enter
    animation(2s,slide)

@keyframes slide
  from
    transform translateX(20rem)
    opacity 0
  to
    transform translateX(0)
    opacity 1

Expected:

On clicking the button, the element should be added to the DOM, then should slide into view with the text Not resolved. As soon as the animation finishes the text should update to My promise is resolved.

Actual:

The element is added to the DOM, and the animation is successfully triggered, but the promise resolves instantly so the text reads My promise is resolved whilst the animation is executing.

What am I doing wrong? Can you create a fork of the plunker where this works (without using $timeout or similar)?


Solution

  • Your current CoffeeScript compiles to this:

    return scope.enter = function() {
      var $elem;
      $elem = angular.element('<div class="donkey">Not resolved</div>');
      return $animate.enter($elem, element).then($elem.html('My promise is resolved!'));
    };
    

    Note that it is not a function that gets passed to then, but instead the instantly executed result of $elem.html('My promise is resolved!'). And since it executes instantly the HTML will change before the promise is resolved.

    It should be:

    $animate.enter($elem, element).then(->
      $elem.html('My promise is resolved!')
    )
    

    And the last part will compile to:

    return $animate.enter($elem, element).then(function() {
      return $elem.html('My promise is resolved!');
    });
    

    And if you don't want the return in the compiled code:

    $animate.enter($elem, element).then(->
      $elem.html('My promise is resolved!')
      return
    )
    

    Demo: http://codepen.io/anon/pen/OPJpzV