Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fire $ngAnimate enter after promise fulfilled

The experience I'm trying to create is one where a background image is first loaded, then an animation is triggered to fade in the element it is attached to. I am doing this in AngularJS using ngAnimate and waitForImages. Specifically, I have the following view in my <body>:

<div ng-view="" ng-class="pageClass">
    <br>
    <br>
    <br>
    <h1 id="loading-text">Loading...</h1>
</div>

Where pageClass is set to landing-page by $routingProvider and the following controller and animation combination are supposed to give me the desired result:

myModule.controller('LandingPageCtrl', ['$timeout', '$animate', function ($timeout, $animate) {
  $animate.on('enter', angular.element('.ng-scope'), function (element) {
    console.log('cool it fired!');
  });
}]).animation('.landing-page', ['$animateCss', function ($animateCss) {
  return {
    enter: function(element, doneFn) {
      console.log('waiting...');
      element.waitForImages(true).done(function () {
        console.log('loaded the image!');

        return $animateCss(element, {
          event: 'enter',
          structural: true
        });
      });
    }
  };
}]);

And here are my SASS classes (scss):

.landing-page {
  &.ng-enter {
            transition: opacity 1s;
    -webkit-transition: opacity 1s;
  }

  &.ng-leave {
            transition: opacity 3s, left 1s ease;
    -webkit-transition: opacity 3s, left 1s ease;
  }

  &.ng-enter,
  &.reverse.ng-leave-active {
    opacity: 1;
    left: 0;
  }

  &.ng-enter-active,
  &.ng-leave,
  &.reverse.ng-enter-active,
  &.reverse.ng-leave {
    opacity: 0;
    left: 0;
  }

  &.ng-leave-active,
  &.reverse.ng-enter {
    opacity: 0;
    left: -100%;
  }
}

The behavior I am experiencing is that after the Loading... text disappears, I get waiting... in the console with simultaneous showing of the element with the background image not loaded completed, then cool it fired!. I have scoured the $animate and $animateCss docs for clues and it looks to me that I am using them correctly and they are just not working as described. If $animate.on('enter',...) is supposed to fire after the enter animation, why is it firing before the loaded the image! console log? Perhaps I'm missing something obvious since I have been looking at this chunk of code for too long...

like image 938
David Rhoderick Avatar asked Nov 09 '22 16:11

David Rhoderick


1 Answers

While this is a solution, it doesn't use ngAnimate the way I want because I guess that's the way Angular apps are. Basically, the problem I was experiencing was that ng-enter was getting fired as soon as the controller was loading the view and no matter what I tried, I couldn't stop/delay it.

So what I did was add a <div> that used ng-show to my view like so:

<div ng-show="waitForBackground">
  <h1 class="intro-text">Some text</h1>
  <p>and content</p>
</div>

That way my controller could work like this:

myAppOrWhatever.controller('LandingPageCtrl', function ($timeout, $animate, $scope) {
  $scope.waitForBackground = false;

  $timeout(function() {
    angular.element('.landing-page div').waitForImages(true).done(function() {
      $scope.waitForBackground = true;
      $scope.$apply();
    });

    $scope.$watch('waitForBackground', function() {
      if($scope.waitForBackground === true) {
        $animate.on('removeClass', angular.element('.landing-page div'), function (element, phase) {
          if(phase === 'close') {
            // do some stuff after the animation is completed
          }
        });
      }
    });
  });

Which is basically a combination of the following two StackOverflow answers:

Angular.js delaying controller initialization

Running code after an AngularJS animation has completed

like image 199
David Rhoderick Avatar answered Nov 15 '22 07:11

David Rhoderick