2014-11-06 39 views
0

這裏plunker它演示了以下行爲: 類NG隱藏從標籤NG-重複刪除之前完成創建數據的HTML視圖,所以當removeClass被觸發元素的高度是不是最終版本,動畫會不正確。如何在ng-repeat完成綁定時運行動畫?

同步數據綁定和動畫的任何解決方案?

的index.html

<!DOCTYPE html> 
<html> 

    <head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <link href="style.css" rel="stylesheet" /> 
    <script src="https://code.angularjs.org/1.2.0/angular.min.js"></script> 
    <script src="https://code.angularjs.org/1.2.0/angular-animate.min.js"></script> 
    <script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script> 
    <script src="app.js"></script> 
    </head> 

    <body ng-app="app"> 
    <div ng-controller="MainController"> 
     <button ng-click="container.toggle()">Toggle</button> 
     <ul class="animation-slider" ng-show="container.show"> 
     <li ng-repeat="item in container.items">{{item}}</li> 
     </ul> 
    </div> 
    </body> 
</html> 

app.js

angular.module('app', [ 
    'ngAnimate' 
]) 

.factory('Container', function($q, $timeout) { 
    return function() { 
    var deferred = $q.defer(); 
    var promise = deferred.promise; 

    var container = { 
     show: false, 
     items: [] 
    }; 

    promise.then(function(data) { 
     container.items = data; 
     container.show = true; 
    }); 

    container.toggle = function() { 
     if (!container.show && container.items.length === 0) { 
     container.load(); 
     } else { 
     container.show = !container.show; 
     } 
    }; 

    container.load = function() { 
     $timeout(function() { 
     deferred.resolve([ 
      'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque feugiat arcu in ligula euismod, vitae rhoncus erat porttitor. In vel metus pulvinar metus fermentum dapibus id nec ligula. Nam ac justo id dolor euismod ornare. Morbi sit amet odio quis sapien sodales ornare dignissim eu risus. Nunc efficitur bibendum odio. Quisque vehicula maximus purus vel blandit. Ut eu molestie urna. Nulla elit ligula, tincidunt sit amet iaculis lobortis, elementum et nunc. Nulla eu egestas massa. Aliquam erat volutpat. Duis consequat cursus nibh ut sodales. Mauris sit amet neque volutpat, sodales lectus a, elementum sapien. In hac habitasse platea dictumst. Proin et blandit nulla. Duis eget tempus lorem.', 
      'Mauris sit amet sodales massa. Pellentesque ut nunc tempus, maximus mauris consectetur, vehicula ex. Vivamus urna urna, lacinia in eros nec, pulvinar porta augue. Proin ullamcorper lacinia purus vitae efficitur. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec in massa in sem iaculis posuere sit amet nec elit. Ut ac nulla eget lorem tristique porta. Aenean ac consequat sem.', 
      'Donec luctus leo a libero vehicula, consequat ullamcorper tortor facilisis. Suspendisse potenti. Etiam sed ultrices nibh, vel maximus enim. Aenean eu nulla vitae lorem commodo tempor. Donec sollicitudin tristique est. Phasellus lobortis et orci vitae posuere. Maecenas auctor cursus porttitor.' 
     ]); 
     //deferred.resolve([1,2]); 
     }, 1000); 
    }; 

    return container; 
    }; 
}) 

.animation('.animation-slider', function() { 
    return { 
    beforeAddClass: function(element, className, done) { 
     if (className === 'ng-hide') { 
     TweenMax.to(element, 1, { 
      height: 0, 
      onComplete: done 
     }); 

     return function() { 
      element[0].style.height = ''; 
     }; 
     } else { 
     done(); 
     } 
    }, 
    removeClass: function(element, className, done) { 
     if (className === 'ng-hide') { 
     var height = element[0].clientHeight; 
     console.log(height); 
     element.css('height', 0); 

     TweenMax.to(element, 1, { 
      height: height, 
      onComplete: done 
     }); 

     return function() { 
      element[0].style.height = ''; 
     }; 
     } else { 
     done(); 
     } 
    } 
    }; 
}) 

.controller('MainController', function($scope, Container) { 
    $scope.container = Container(); 
}); 

回答

1

如果你想設置container.showtrue最後ng-repeat元素已加蓋了只後,您可以創建一個鐘錶指示$last屬性爲true上的加蓋元素。當它是true時,該指令可以將container.show設置爲true

所以,你的HTML應該是這樣的,有一個新的handle-last-item-stamped指令的重複li元素:

<ul class="animation-slider" ng-show="container.show"> 
    <li ng-repeat="item in container.items" handle-last-item-stamped="$last">{{item}}</li> 
</ul> 

而新指令是這樣的(我的情況下,注射$timeout你需要添加一個輕微顯示前)延遲:

.directive('handleLastItemStamped', ['$timeout', function($timeout){ 
    return { 
    restrict: 'A', 
    link: function (scope, element, attrs){ 
     scope.$watch(attrs.handleLastItemStamped, function (newVal, oldVal){ 
     if (newVal) { 
      scope.container.show = true; 
     } 
     }); 
    } 
    } 
}]); 

,當然,你必須從你的promise.then刪除container.show = true;

下面是這些變化的普拉克: http://plnkr.co/edit/nVG6gh7vabYhqg5nAula

+0

其天才的想法! Thx的詳細答案! – axon 2014-11-08 06:39:15

+0

不客氣!樂意效勞。 – MikeJ 2014-11-09 14:24:13