SkelDave
SkelDave

Reputation: 1186

Knockout - Element Becomes Undraggable - HTML5 Drag and Drop

I'm using this knockout binding to add html5 drag and drop to my application.

https://github.com/bramstein/knockout.dragdrop

I have two observable arrays with items that can be dragged between them.

On page load all the items in both lists are draggable and work as expected.

The problem occurs when I try to drag items back to their original list, the drag and drop stops working.

As you can see from my console.log, I have dragged and held the element for a few seconds and then dropped it into list 2.

When I try and drag that same element back to list 1, the drag start and drag end triggers instantly.

Below is my data-bind for list 1

    <ul data-bind="
        dropzone: { name: 'unassigned', drop: $root.DropUnassignedStandard }">

        <!-- ko foreach: DupeStandards -->
            <li data-bind="text: Name, 
                dragzone: { name: 'assigned', dragStart: $root.onStart, dragEnd: $root.onEnd }" draggable="true" />
        <!-- /ko -->
    </ul>

Below is my data bind for list 2

<div data-bind="
    dropzone: { name: 'assigned', drop: $root.DropAssignedStandard }">

    <ul>
        <!-- ko foreach: UnassignedDupeStandards -->             
        <li data-bind="text: Name, 
            dragzone: { name: 'unassigned', dragStart: $root.onStart, dragEnd: $root.onEnd }" draggable="true" />     
         <!-- /ko -->
    </ul>
</div>

Below is my onStart function

self.onStart = function (data) {

    var currentDate = new Date();
    var datetime = currentDate.getHours() + ":"
        + currentDate.getMinutes() + ":"
        + currentDate.getSeconds();

    console.log('dragStart - ' + datetime);
}

Below is my onEnd function

self.onEnd = function (data) {

    var currentDate = new Date();
    var datetime = currentDate.getHours() + ":"
        + currentDate.getMinutes() + ":"
        + currentDate.getSeconds();

    console.log('dragEnd - ' + datetime);
}

Below is the function to move items from list 1 to list 2

self.DropAssignedStandard = function (droppedStandard) {

    self.UnassignedDupeStandards.push(droppedStandard);

    var user = ko.utils.arrayFirst(self.Users(),
        function (user) {
            return ko.utils.arrayFirst(user.DupeStandards(),
                function (ds) {
                    return ds.DupeStandardID === droppedStandard.DupeStandardID;
                });
        });

    user.RemoveStandard(droppedStandard);
}

Below is the function to move items from list 2 to list 1

self.DropUnassignedStandard = function (droppedStandard, user) {
    user.AddStandard(droppedStandard);
    self.UnassignedDupeStandards.remove(droppedStandard);
}

Any help is appreciated, thanks.

Upvotes: 0

Views: 369

Answers (2)

SkelDave
SkelDave

Reputation: 1186

Turns out it is a bug with chrome.

When modifying the DOM on dragstart it apparently breaks html5 drag and drop functionality.

Thanks to the other answers.

dragend, dragenter, and dragleave firing off immediately when I drag

Upvotes: 1

Jason Spake
Jason Spake

Reputation: 4304

Are you also seeing the error "user.AddStandard is not a function" in your console? I think the problem is the knockout context for your drop event.

<ul data-bind="
    dropzone: { name: 'unassigned', drop: $root.DropUnassignedStandard }">

In the DropUnassignedStandard function it appears your assumption was that the second argument would be the user.

self.DropUnassignedStandard = function (droppedStandard, user) {
    user.AddStandard(droppedStandard);
    self.UnassignedDupeStandards.remove(droppedStandard);
}

Unfortunately because the data-bind is attached outside of the foreach the second argument is the root view-model instead, and user.AddStandard will error. You'll need a different way to determine which user the item belongs to. Perhaps similar to what you have in the DropAssignedStandard function.

Upvotes: 0

Related Questions