angular.bind()表示'drop'事件监听器行为不正常

时间:2013-03-20 20:05:47

标签: angularjs angularjs-directive

Plunker demonstrating code

我有一个<div>元素,其中指令dragAndDrop设置为属性:

<div ng-class="divClass" drag-and-drop>Drop files here</div>

(作为一方,不太重要的说明,ng-class的行为不符合预期,但那是separate issue 我想要的是用户将文件从桌面拖放到div。在这样做的时候,我使用angular.bind()来检测丢弃事件。当然,一旦他们放弃,我就会调用e.stopPropagation()e.preventDefault(),但页面会继续,无论如何重定向页面。我做错了什么会妨碍上述两种方法的执行?

dragAndDrop指令:

directive('dragAndDrop', function() {
  return {
    restrict: 'A',
    link: function($scope, elem, attr) {
      elem.bind('dragenter', function(e) {
        e.stopPropagation();
        e.preventDefault();
        // still can't get this one to behave:
        // https://stackoverflow.com/q/15419839/740318
        $scope.divClass = 'on-drag-enter';
      });
      elem.bind('dragleave', function(e) {
        e.stopPropagation();
        e.preventDefault();
        $scope.divClass = '';
      });
      elem.bind('drop', function(e) {
        var droppedFiles = e.dataTransfer.files;
        // It's as though the following two methods never occur
        e.stopPropagation();
        e.preventDefault();

        if (droppedFiles.length > 0) {
          for (var i=0,ii=droppedFiles.length;i<ii;i++) {
            $scope.files.push(droppedFiles[i]);
          }
        }
      });
    }
  };
});

1 个答案:

答案 0 :(得分:11)

Angular不知道您注册的事件处理程序何时被触发,因此您需要通知Angular您已更改范围变量。您可以使用$apply函数执行此操作。

$scope.$apply(function () {
    $scope.divClass = 'on-drag-enter';
});

当涉及到drop处理程序时,你是正确的 - var droppedFiles = e.dataTransfer.files;之后的语句永远不会运行,因为语句导致了运行时错误。

e是一个jQuery事件,而dataTransfer是实际DOM事件的属性。要解决此问题,您需要通过originalEvent属性访问原始事件。

var droppedFiles = e.originalEvent.dataTransfer.files;

<强>更新

e.originalEvent只有在角度之前包含jQuery时才需要,但由于你没有在你的plnkr中做到这一点,该解决方案无效,我为此道歉。

似乎你需要选择preventDefault of the dragover event的支持(也许这可以在其他事件中完成 - 没有经过测试。)

elem.bind('dragover', function (e) {
    e.stopPropagation();
    e.preventDefault();
}); 

Updated plnkr