它只适用于$应用但抛出$digest已经在进行中



我正在尝试实现一个可排序的drag-n-drop。我尝试了ng sortable和其他一些,但我有一些角落的案例,我没有设法根据自己的需求进行调整,而是决定自己做。

我有可拖动、可丢弃和主ui路由器视图/控制器的指令。

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

它运行良好,但抛出了一个$digest已在进行中的错误。

这是因为在该指令中,我用$apply包装对handleDrop()的调用,然后在handleDop内部,我用另一个$apply包裹函数的一部分。显然不正确,但这是我让它工作的唯一方法——因为除了错误之外,一切都很好。

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

根据类似问题的答案,我尝试用$timeout替换handleDrop()中的$apply,然后只要我不注入$timeout,它就可以工作,但这显然会引发"$timeout未定义",但它也可以工作。

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

下面是我的指令和控制器的精简版本,我认为这是重要的部分。drop()是在要处理的html中指定的。

任何关于我做错了什么的帮助都非常感谢

指令:

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');}); 
    };

相反,如果$apply()使用$timeout作为应用触发器摘要,但超时会将其安排为下一个摘要进程运行,尽管我不确定您的代码是否需要它,但您不会将任何内容分配给当前$apply 中的作用域

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

最新更新