它仅适用于。$ apply但是已经在进行中抛出$ digest

时间:2014-09-16 09:05:57

标签: angularjs angularjs-directive

我正在尝试实施可排序的拖放操作。我尝试过可排序的和其他一些但我有一些极端情况,我没有设法根据我的需要调整它们并决定自己做。

我有draggable,droppable和主ui-router视图/控制器的指令。

我正在传递一个函数('handleDrop()'),接受从控制器到droppable指令的一些参数。我希望函数在从指令调用时更新主视图/控制器范围中的模型。

它工作正常,但是已经在进行错误中抛出$ digest。

这是因为在指令中,我用$ apply包装对handleDrop()的调用,然后在handleDrop中,我将部分函数包装在另一个$ apply中。显然不正确,但这是我开始工作的唯一方法 - 因为除了错误之外一切正常。

如果我删除了handleDrop()中的$ apply,那么视图只会得到部分更新(例如,我得到一个li元素附加到我的列表但是空的 - 没有相应的数据。

我尝试用$ timeout基于类似问题的答案替换handleDrop()中的$ apply,然后只要我没有注入$ timeout就可以工作但显然会抛出“$ timeout is not defined” - 但它也有效。

如果我将$ timeout注入控制器,我没有得到这样的错误(如预期的那样)但是dom没有再次正确更新..

在我的指令和控制器的剥离版本下面,我认为是重要的部分。 drop()在html中指定为handleDrop()。

对我所做错的任何帮助都非常感谢

指令:

app.directive('droppable', function() {
   return {
    scope: {
      drop: '&',
      bin: '='
    },
  link: function(scope, element) {
    var el = element[0];

  el.addEventListener(
    'drop',
    function(e) {
      if (e.stopPropagation) e.stopPropagation();

      var item = document.getElementById(e.dataTransfer.getData('text/plain'));
      // Putting additional data  into variables newStage etc

      // call the passed drop function
      scope.$apply(function(scope) {
        var fn = scope.drop();
        if ('undefined' !== typeof fn ) {            
          fn(item, newStage, prevStage, newIndex); 
            document.getElementById(someHtmlElementIdIHave).appendChild(item); 
            }   
        }
      });

      return false;
    },
    false
  );

控制器:

  .controller('funnelCtrl', function ($scope, $state, $http, someObject) {
    $scope.handleDrop = function(item, newStage, prevStage, newIndex) {

      $http.put('/api/funnel/' + item.id, {some object}).
        success(function (data) {   
                    $timeout(function(){
                        $scope.someObject[newStage].splice(newIndex, 0, item.optyId) ;
                        $scope.someObect[prevStage].splice(prevIndex,1);                            
                    });                         
        }).
        error(function (data) {alert('Error Saving');}); 
    };

1 个答案:

答案 0 :(得分:1)

相反,如果$apply()使用$timeout作为apply触发摘要,但超时会安排它运行下一个摘要进程,虽然我不太确定你甚至需要它与你的代码,你不要t为当前$apply

中的范围指定任何内容
$timeout(function(scope) {
  var fn = scope.drop();
  if ('undefined' !== typeof fn ) {            
    fn(item, newStage, prevStage, newIndex); 
    document.getElementById(someHtmlElementIdIHave).appendChild(item); 
  }   
})