2014-10-04 31 views
2

我有一个简单的问题,angularui bootstrapcollapse指令。我有一个<select>菜单。当某人改变菜单时,内容改变。但是,我想在应用这些更改之前添加动画。具体而言,我希望在展示新内容之前,该部分可以折叠并展开。我可以将它坍塌,但我想知道如何检测崩溃何时完成,以便我可以将它收缩。AngularJS - 查找崩溃动画结束

我可以使用我当前使用的$timeout方法,但它感觉“hackish”和“不正确”,因为如果折叠动画的时间发生变化,那么我不得不再次改变时间。

Relavent代码:

.directive("myBufferAnimation", function($timeout) { 
    var ignoreFirst = true; 
    return function(scope, element, attrs) { 
     scope.$watch("selectBuffer", function(newValue) { 
      if (ignoreFirst) { 
       ignoreFirst = false; 
       return; 
      } 


      scope.toCollapse = true;  
      // Detect end of animation here? 
      // Bogus solution, as this just waits for one second rather than listening for the end of animation 
      $timeout(function() { 
       scope.selected = newValue; 
       scope.toCollapse = false; 
      }, 1000); 
     }); 
    } 
}); 

jsfiddle说明问题。

回答

1

看看这个angularui引导的崩溃指令,它使用$ transition服务执行动画,但它并没有暴露出来挂钩到服务的promise返回。但是,它会更改具有collapse指令的元素的类名称。您可以通过在元素的class属性中加入监视来确定何时完成合拢动画。

下面是观察元素上的类的代码的一个工作示例。我改变了使用ng-change来执行动画,而不是看着selectBuffer。这消除了对变量ignoreFirst的需求。

angular.module("testApp", ["ui.bootstrap"]).controller("TestCtrl", function($scope) { 
 
    // This would actually be fetched from an ajax call 
 
    $scope.data = [{ 
 
    "title": "Title 1", 
 
    "content": "Content 1" 
 
    }, { 
 
    "title": "The Second Title", 
 
    "content": "Some content goes here" 
 
    }, { 
 
    "title": "Title 3", 
 
    "content": "Content 3" 
 
    }]; 
 
    $scope.selected = $scope.data[0]; 
 
    $scope.selectBuffer = $scope.data[0]; 
 
    $scope.toCollapse = false; 
 
}).directive("myBufferAnimation", function($timeout) { 
 
    return function(scope, element, attrs) { 
 
    scope.valueChanged = function() { 
 
     scope.toCollapse = true; 
 
     // save off the unregister method returned from $watch call. 
 
     var unregisterWatch = scope.$watch(function() { 
 
     return element.attr('class'); 
 
     }, function(newClass, oldClass) { 
 
     // If the newClass is 'collapse' and the oldClass is 'collapsing' 
 
     // this means that the collapsing animation has completed. 
 
     if (newClass.indexOf("collapse") !== -1 && oldClass.indexOf("collapsing") !== -1) { 
 
      scope.selected = scope.selectBuffer; 
 
      scope.toCollapse = false; 
 
      // unregister the $watch on the class attribute 
 
      // since it is no longer needed. 
 
      unregisterWatch(); 
 
     } 
 
     }); 
 
    }; 
 
    } 
 
});
<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <link data-require="[email protected]" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" /> 
 
    <script src="https://code.angularjs.org/1.2.26/angular.js"></script> 
 
    <script data-require="[email protected]*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
    <script data-require="[email protected]" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script> 
 
    <script data-require="[email protected]" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script> 
 
</head> 
 

 
<body> 
 
    <div ng-app="testApp"> 
 
    <div ng-controller="TestCtrl"> 
 
     <select ng-options="opt as opt.title for opt in data" ng-model="selectBuffer" ng-change="valueChanged()"></select> 
 
     <br /> 
 
     <div my-buffer-animation="" collapse="toCollapse" class="test"> 
 
     <h1>{{selected.title}}</h1> 
 

 
     <p>{{selected.content}}</p> 
 
     </div> 
 
    </div> 
 
    </div> 
 
</body> 
 

 
</html>

+0

我注意到你用'的NewClass === “崩溃”'。即使有其他类(因为'newClass'可能会''折叠我的自定义类''或什么的,对吧?)这样工作吗?) – soktinpk 2014-11-22 13:50:57

+0

最新评论更新:我添加了'test-class'到'div '用'my-buffer-animation'指令和上面的代码停止工作,但我认为这可以使用'element.hasClass'或等价物来解决。 – soktinpk 2014-11-22 14:01:16

+0

我尝试过测试你建议的更改,但我在使用的浏览器中出现错误,这可能是由于使用了'classList',并且angularjs获取旧值传递给watch函数的方式。我使用'indexOf'来确定是否存在应该处理多个类名的类名。 'indexOf'可能对于每种情况都不够健壮,但它应该足以满足你正在做的事情。 – 2014-11-22 14:51:23