2

As title, please see this fiddle:

http://jsfiddle.net/goodwill/ezNuj/

Which I have added a directive with following code:

myApp.directive('ngFadeIn', function() {
  return function(scope, element, attr) {
    if (element.is('tr, tbody')) {
      element.find('td').effect("highlight", {}, 500);
    } else {
      element.effect("highlight", {}, 500);
    }
    return scope.destroy = function(complete) {
      return element.fadeOut(500, function() {
        if (complete) {
          return complete.apply(scope);
        }
      });
    };
  };
});

The problem I have is when the page is first loaded, because I have applied the directive in the ng-repeat element, all the items got highlight effect (flashing once) when the page is first loaded. How can I skip this effect without too much hack (ideally, everything done inside the directive)

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
William Yeung
  • 10,368
  • 9
  • 36
  • 42

4 Answers4

0

Interesting, I'm not sure if there is a simple, clean solution for this. It seems that ngRepeatDirective is built not to care if the repeater is running for the first time or if it's just adding new items to the list. And therefor it doesn't let you take different actions depending on that. AngularUI's ui-animate directive doesn't seem to solve this issue either, so I'm not sure if this is doable right now without resorting to pesky timeouts.

What you could do is modify ngRepeatDirective to check for something like a ng-repeat-finished attribute and execute that after the repeater has finished. Then it should be trivial to add logic to avoid animation on the first repeater.

By the way, you shouldn't name your directives with the ng prefix since that is what Angular uses internally. You should come up with your own prefix for your application.

Anders Ekdahl
  • 22,685
  • 4
  • 70
  • 59
0

If we could determine when the page has finished rendering for the first time, then we could set some property on a service or rootScope, which your directive could inject, and hence examine this property to determine whether or not to apply the animation.

Unfortunately, there doesn't appear to be a way to determine when the page has finished rendering. See AngularJS - How to query the DOM when directive rendering is complete, which is addressing the same issue.

The only workaround I can think of is to create another directive (use it once on the page) that would use $timeout to simply delay 1 second or so, then do what I mentioned above: set some property on a service or rootScope. Your fadeIn directive would $watch that property/variable and when the value changes, it could set some local property/boolean/flag that allows or prevents the animation.

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
0

I would check out angular's built in animations just released in version 1.1.14. Here is a great write-up on the new features: Animation in AngularJS. In particular I would check out the section on "conditionally enable/disable animations". From their site:

JS:

//turn on the animation
$scope.myAnimation = { enter: 'cool-enter', leave: 'cool-leave' };

//change the animation
$scope.myAnimation = { enter: 'uncool-enter', leave: 'uncool-leave' };

//remove the animation
$scope.myAnimation = null;

HTML:

<div data-some-directive data-ng-animate="myAnimation"></div>

Again note, this requires the currently unstable version of angular js 1.1.14

Chris Montgomery
  • 2,344
  • 2
  • 19
  • 30
  • Yeah unfortunately we probably need that on the stable release as there are quite a bit directives doesn't work on 1.1.x – William Yeung Apr 18 '13 at 09:19
0

I have the same issue using angular 1.4.9. I don't want ng-repeat animation happen the first time. The only way I found to make that work is to have a custom directive on ng-repeat parent and disable animation for a short time:

(function (){
  'use strict';

  angular
    .module('directives')
    .directive('disableLoadingAnimation', disableLoadingAnimation);

  function disableLoadingAnimation($animate, $timeout) {
    var directive = {
      link: link,
      restrict: 'A'
    };
    return directive;

    function link(scope, element) {
      $animate.enabled(element, false);
      $timeout(function (){
        $animate.enabled(element, true);
      }, 1000);
    }
  }
})();

HTML

<table disable-loading-animation>
   <tr ng-repeat="line in lines">...</tr>
</table>

I don't like the fact that I have to set a 1000ms delay but it's the cleaner way I found so far.

mchasles
  • 1,173
  • 1
  • 8
  • 14