【问题标题】:It only works with .$apply but throws $digest already in progress它只适用于 .$apply 但抛出 $digest 已经在进行中
【发布时间】:2014-09-16 09:05:56
【问题描述】:

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

我有可拖动、可放置和主 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');}); 
    };

【问题讨论】:

  • 正确的@maurycy,结果我根本不需要任何 $apply,我的错误是在将新元素添加到数组时出错。我仍然对它为什么起作用感到困惑以前使用双重应用..

标签: angularjs angularjs-directive


【解决方案1】:

如果$apply() 使用$timeout 作为应用触发摘要,但超时将安排它为下一个摘要进程运行,虽然我不太确定你的代码是否需要它,但你不分配任何东西当前$apply中的作用域

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

【讨论】:

  • 谢谢。我得到“无法读取未定义的属性'drop'”运行此代码。我注入了 $timeout 并尝试了这个,但是现在范围变量似乎不可用,有什么想法吗?
  • 代码sn -p 没解决,但是错误不是双$apply引起的就对了
猜你喜欢
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 2014-03-18
  • 2023-03-28
  • 2014-10-01
  • 1970-01-01
  • 2014-09-28
  • 1970-01-01
相关资源
最近更新 更多