marceljuenemann / angular-drag-and-drop-lists

Angular directives for sorting nested lists using the HTML5 Drag & Drop API
MIT License
2.16k stars 713 forks source link

dnd-drop callback fires on ancestor when dropping element on a nested child list #443

Open rettgerst opened 6 years ago

rettgerst commented 6 years ago

to demonstrate this bug I checked out the repo and made some small changes to the nested list example:

in the list.html template I added a dnd-drop attribute with a callback:

<script type="text/ng-template" id="list.html">
    <ul dnd-list="list"
    dnd-drop='ondropCallback()'
    >
        <li ng-repeat="item in list"
            dnd-draggable="item"
            dnd-effect-allowed="move"
            dnd-moved="list.splice($index, 1)"
            dnd-selected="models.selected = item"
            ng-class="{selected: models.selected === item}"
            ng-include="item.type + '.html'">
        </li>
    </ul>
</script>

and in the nested.js controller I added that callback:

$scope.ondropCallback = function () {
    console.log('ondropCallback');
}

now try dropping an item inside a container.

the ondropCallback callback fires once for the list the element was dropped on, and once for every ancestor list. this means it's impossible to use callbacks for nested lists.

jasonpeate commented 6 years ago

I am having the same problem

Nilloc1234 commented 3 years ago

I encountered the same problem when building a solution for our application. The fix I have stumbled upon is by capturing the 'event' variable in my drop-event function and then calling stopPropagation() on that event variable at the beginning of that function call. Referencing the function on the original comment it would look something like this:

<script type="text/ng-template" id="list.html">
    <ul dnd-list="list"
    dnd-drop='ondropCallback(event)'
    >
        <li ng-repeat="item in list"
            dnd-draggable="item"
            dnd-effect-allowed="move"
            dnd-moved="list.splice($index, 1)"
            dnd-selected="models.selected = item"
            ng-class="{selected: models.selected === item}"
            ng-include="item.type + '.html'">
        </li>
    </ul>
</script>
$scope.ondropCallback = function (event) {
        event.stopPropagation();
    console.log('ondropCallback');
}