Reputation: 4539
I am using native HTML drag'n'drop in my angular app and I found this event flickering problem
This answer doesnt solve my issue, as they are moving the element manualy. I am leaving it on native implementation.
My simplified code:
var app = angular.module('app', []);
app.directive('amDnd', function() {
return {
scope: true,
link: function($scope, $element, $attr) {
var el = $element[0];
el.draggable = true;
el.addEventListener('dragenter', function dragEnter(e) {
console.log($scope.$id, 'dragEnter');
}, false);
el.addEventListener('dragleave', function dragEnter(e) {
console.log($scope.$id, 'dragleave');
}, false);
}
};
});
div[am-dnd] {
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div am-dnd>
<p>DRAG ME</p>
</div>
<div am-dnd>
<h3>DRAG OVER THIS AREA</h3>
<p>See the console, drag enter and leave are fired again and again while draging over
</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi quisquam, eaque, iure mollitia similique magnam voluptatem blanditiis distinctio nemo! Laboriosam porro iste maiores sequi magnam similique ad, in at. Omnis.</p>
</div>
</div>
Upvotes: 4
Views: 4195
Reputation: 4539
Solution which best fits my needs:
var app = angular.module('app', []);
app.directive('amDnd', function() {
return {
scope: true,
link: function($scope, $element, $attr) {
var el = $element[0],
counter = 0;
el.draggable = true;
el.addEventListener('dragenter', function dragEnter(e) {
if (e.target === el && !counter) {
console.log($scope.$id, 'dragEnter');
}
counter++;
}, false);
el.addEventListener('dragleave', function dragLeave(e) {
counter--;
if (e.target === el && !counter) {
console.log($scope.$id, 'dragleave');
}
}, false);
}
};
});
div[am-dnd] {
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div am-dnd id='id1'>
<p>DRAG ME</p>
</div>
<div am-dnd id='id2'>
<h3>DRAG OVER THIS AREA</h3>
<p>See the console, drag enter and leave are fired again and again while draging over
</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi quisquam, eaque, iure mollitia similique magnam voluptatem blanditiis distinctio nemo! Laboriosam porro iste maiores sequi magnam similique ad, in at. Omnis.</p>
</div>
</div>
Upvotes: 1
Reputation: 7433
I've got a feeling that root of the "flickering" issue is that the dragenter
/dragleave
events are occurring for each child element of the second am-dnd
directive. There's a Stack Overflow question that discusses fixes for this here.
You might be able to declare a CSS rule like this:
.child-elements {
pointer-events: none;
}
... and apply this class to all child elements of the am-dnd
directive using jqLite during the event trigger:
element.children().addClass("child-elements");
I made a JSFiddle where the "flickering" events are minimized when the first directive is dragged over the second, but there's still some issues with the second directive being dragged over the first. Nevertheless, I hope this points you in the right direction.
var app = angular.module('app', []);
app.directive('amDnd', function () {
return {
scope: true,
link: function (scope, element, attrs) {
element.attr('draggable', 'true');
element.on('dragenter', function () {
element.children().addClass("child-elements");
console.log('dragEnter');
});
element.on('dragleave', function () {
element.children().removeClass("child-elements");
console.log('dragleave');
});
}
};
});
Upvotes: 5