3

Plunker 演示代码

我有一个将指令设置为属性的<div>元素:dragAndDrop

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

(作为一个方面,不太重要的说明,ng-class 的行为不符合预期,但这是一个单独的问题 我希望用户将文件从他们的桌面拖放到 div。不过,这样做后,我会使用它angular.bind()来检测 drop 事件。当然,一旦它们掉线,我就会调用e.stopPropagation()and 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]);
          }
        }
      });
    }
  };
});
4

1 回答 1

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仅当您在 Angular 之前包含 jQuery 时才需要,但由于您尚未在 plnkr 中执行此操作,因此该解决方案无效,对此我深表歉意。

似乎您需要通过preventDefaultdragover 事件选择支持放置(也许这也可以在其他事件中完成 - 尚未测试。)

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

更新了 plnkr

于 2013-03-20T21:03:56.137 回答