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]);
}
}
});
}
};
});
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With