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:
- User Drags an item to a div
- On the drop an AJAX Post is sent to a controller action with the item ID
- 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.
- 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.
精彩评论