开发者

jQuery UI Draggable & Droppable breaks after AJAX Post to Controller Action MVC.NET

I'm having a problem getting this functionality to work.

Situation is:

  1. User Drags an item to a div
  2. On the drop an AJAX Post is sent to a controller action with the item ID
  3. On success I replace the div the item was dropped onto with html markup retrieved from the database. .replaceWith(data) Note: This markup is a div with the same ID as that which the item was dropped onto with some additional elements contained within.
  4. This loads the updated div.

All this works perfectly, well almost, the problem is that I cannot drag a different item onto the div. I'm sure it has something to do with the new div (with the same ID) being loaded in after the AJAX Post.

Here's my jQuery code

$(function () {
        $('.draggable').draggable({ revert: true });
        $('#layoutHeader').droppable({
            drop: function (event, ui) {
                $.ajax({
                    type: "POST",
                    url: '/SiteSetup/GetMarkup/' + $(ui.draggable).attr("id"),
                    success: function (data) {
                        $('.draggable').draggable('destroy');
                        $('#layoutHeader').replaceWith(data);
                        $('.draggable').draggable({ revert: true });

                    }
                });
            }
 开发者_如何学编程       });
    });


With jQuery and DOM, if you replace a DOM element with exactly the same DOM element with exactly the same DOM id ( so a div with id "div1" gets replaced by another div with id "div1") then the associated jQuery data with that DOM element gets lost. jQuery's pointer actually points to a ghost element which no longer exist on the page.

To see the proof, fire up firebug in Firefox and simply go

$("#layoutHeader")

before and after your AJAX post. Click on the element returned in the console both the times. You will notice that on the second click (i.e. one after the POST returns) your firebug will point to a greyed out ghost element.

Solution is to refactor your code a bit. Try this

function handler(event,ui){
                $.ajax({
                    type: "POST",
                    url: '/SiteSetup/GetMarkup/' + $(ui.draggable).attr("id"),
                    success: function (data) {
                        $('.draggable').draggable('destroy');
                        $('#layoutHeader').replaceWith(data);
                        $('.draggable').draggable({ revert: true });

                    }
             $('#layoutHeader').droppable({drop: handler});
}


$(function () {
        $('.draggable').draggable({ revert: true });
        $('#layoutHeader').droppable({drop: handler});

    });


Keeping the id of the HTML you're inserting into the DOM isn't going to preserve the droppable widget that was attached to the div you're replacing.

You'll need to restructure your code so that the droppable widget is re-initialized on the new content:

$('.draggable').draggable({ revert: true });

function createDroppable() {
    $('#layoutHeader').droppable({
        drop: function (event, ui) {
            $.ajax({
                type: "POST",
                url: '/SiteSetup/GetMarkup/' + $(ui.draggable).attr("id"),
                success: function (data) {
                    $('.draggable').draggable('destroy');
                    $('#layoutHeader').replaceWith(data);

                    /* Re-initialize the droppable widget: */
                    createDroppable();

                    $('.draggable').draggable({ revert: true });
                }
            });
        }
    });
}   

createDroppable();

Alternatively, you could wrap #layoutHeader with another div that acts as the droppable. That way, replacing #layoutHeader shouldn't remove the droppable functionality.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜