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

angularjs, angularjs-directive

Solution

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 `preventDefault` of the dragover event (Perhaps this can be done in other events as well--haven't tested.)

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

Updated plnkr.

Problem

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

Original source