Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:
        // 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]);
          }
        }
      });
    }
  };
});
like image 561
Scott Avatar asked Mar 16 '26 17:03

Scott


1 Answers

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.

like image 142
Martin Avatar answered Mar 19 '26 10:03

Martin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!