Итак, у меня есть простой ng-repeat с анимацией ввода, определенной в javascript.
Песочница: http://codepen.io/anri82/pen/KwgGeY
код:
<div ng-app="myApp" ng-controller="MyController">
{{state}}
<ul>
<li class="repeat-animate" ng-repeat="item in list">{{item}}</li>
</ul>
<button ng-click="add()">add</button>
</div>
angular.module('myApp', ['ngAnimate'])
.controller("MyController", function($scope) {
$scope.state ="idle";
$scope.id=3;
$scope.list = [1,2];
$scope.add = function () {
$scope.state="pushing";
$scope.list.push($scope.id++);
$scope.state="done pushing";
};
}).animation('.repeat-animate', function () {
return {
enter: function (element, done) {
element.hide().show(2000, done);
}
};
});
Как переключить $scope.state
в done pushing
только после завершения анимации? Ответ должен быть в angular, не предлагайте setTimeout
.
С помощью подхода javascript-анимации, который вы делаете, вам нужно овладеть областью текущего элемента в обработанном анимацией обратном вызове. Поскольку после обновления переменной вне контекста angular вам нужно вручную вызвать цикл дайджеста, выполнив $scope.$apply()
(или используйте $timeout
, scope.$evalAsync
и т.д.). А также, поскольку ng-repeat создает дочернюю область, область элемента фактически имеет унаследованное свойство state
из области родительского контроллера, поэтому для того, чтобы обновление получило отражение в родительской области, используйте объект для обертывания state
, так что оба дочерних объекта и родительского объекта имеют одну и ту же ссылку на объект.
angular.module('myApp', ['ngAnimate'])
.controller("MyController", function($scope) {
$scope.push = {state: "idle" };
$scope.id=3;
$scope.list = [1,2];
$scope.add = function () {
$scope.push.state="pushing";
$scope.list.push($scope.id++);
};
}).animation('.repeat-animate', function () {
return {
enter: function (element, done) {
element.hide().show(2000, function(){
var scope = element.scope(); //Get the scope
scope.$evalAsync(function(){ //Push it to async queue
scope.push.state="done pushing"
});
});
}
};
});
"done pushing"
scope.$evalAsync
"done pushing"
вscope.$evalAsync
, что ничем не отличается от выполненияscope.push.state="done pushing"; scope.$evalAsync();