angular.bind() for 'drop' event listener not behaving properly

Plunker demonstrating code

I have a <div> element with the directive dragAndDrop set as an attribute:

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

(as a side, and less important note, ng-class is not behaving as expected, but that's a separate issue) What I would like is for users to drag and drop files from their desktop to the div. Upon doing so though, I use angular.bind() to detect the drop event. Of course once they drop, I call e.stopPropagation() and e.preventDefault(), but the page continues on with redirecting the page regardless. What am I doing wrong that would prevent the two aforementioned methods from executing?

dragAndDrop directive:

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:
        // http://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]);
          }
        }
      });
    }
  };
});

Angular doesn't know when event handlers you have registered are triggered, so you need to notify Angular that you've changed scope variables. You do that with the $apply function.

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

When it comes to the drop handler you're correct--the statements after var droppedFiles = e.dataTransfer.files; are never run because of the runtime error that statement results in.

e is a jQuery event, whereas dataTransfer is a property on the actual DOM event. To fix the problem you need to access the original event through the originalEvent property.

var droppedFiles = e.originalEvent.dataTransfer.files;

Update

e.originalEvent is only needed if you have included jQuery before angular, but since you haven't done that in your plnkr, that solution was invalid, I apologize for that.

It seems like you need to opt in for drop support by listening to the dragover event and set the dropEffect. (Perhaps this can be done in other events as well--haven't tested.)

elem.bind('dragover', function (e) {
    e.stopPropagation();
    e.preventDefault();
    e.dataTransfer.dropEffect = 'copy';
}); 

Updated plnkr.