开发者

JQuery Dialog: How to do partial page refresh and get new dialogs each time

I'm having a workflow issue with my JQuery dialogs when trying to create the dialogs and then doing a partial page render. I'll try to go through a sample scenario, and my apologies in advance for the long problem description:

The page loads, with the html that I would开发者_开发问答 like to be turned into JQuery dialogs. The dialogs are created on document.ready (using .dialog()), but the autoOpen property is set to false. When JQuery creates the dialogs (if I'm using Firebug to inspect the page), the dialog html is actually stripped from its normal location and stuck at the very end of the document, with some wrapper classes around it. The user opens the dialogs by clicking a link that just does a $dialogDiv.dialog('open').

So that all works fine. The problem is that there are times when I am doing a partial page reload using AJAX (using ASP.NET MVC RenderPartial). The part of the page I'm refreshing happens to have all of the dialog html in it, so that gets re-written out. But remember the dialog (with all of the JQuery wrapper classes, etc) is already there a the bottom of the document. That html wasn't part of the page refresh, so now I'm stuck with two sets of dialog html. This is giving me all sorts of problems because I have duplicate id's on the page, and the jQuery behavior on these html elements becomes unpredictable. It's even worse when I start doing 3, 4, 5 partial page refreshes, because then I have 3, 4, 5 sets of dialog html (with only one real dialog having been made on document.ready).

I'm thinking that I might need to destroy the dialogs or something at some point, but I haven't had any luck with this approach. Does anyone have any ideas?

Thanks very much.


According to the docs destroying a dialog removes dialog functionality and restores it to it's pre-init state but does not remove it from the DOM.

Since you are replacing the content and the dialog you could just remove the old ones.

$.ajax({
  url: '/some/url/',
  success:function(data){
    $('.ui-dialog').empty().remove();
    //add the new html and make the dialogs
  }
});

In response to you comment

I haven't seen you code, so I'm not exactly sure how you're settings up the dialogs, but in a general sense I would populate a variable with only the dialogs that will be replaced.

//inside document.ready
  var myDialog=$('#myDialog').dialog(),
  myOtherDialog=$('#myOtherDialog').dialog(),
  permanentDialog=$('#permanentDialog').dialog(),
  destroyableDialogs=[myDialog, myOtherDialog];

//ajax callback
success: function(data){
  $.each(destroyableDialogs, function(i,n){
    n.empty().remove();
  });
}


After working through this problem and the prior answer given, I discovered some important details missing from the answer. The most important point here is that while .dialog("destroy") does restore the div to its pre-init state, it DOES NOT restore the div to its original location in the DOM. (BAHDev's question mentions how UI Dialog moves the div in the first place.) This is critical to the Ajax operation and this change/non-change of the div location should be clarified in the jQuery documentation (that would have saved me a lot of time).

If Ajaxing only the contents of the dialog div, then this behavior probably is not critical since you can easily find and rewrite the div contents no matter where it resides in the DOM. If your dialog content gets Ajaxed inline with other objects, however, then moving a div from its original location will likely cause later Ajaxing to create another div in the original location resulting in multiple divs of the same ID.

For example, I request a short list of products and a long list of products in one Ajax call. The short list goes to the screen and the long list goes to a hidden dialog. Because the lists are related, it makes sense to grab them both in one Ajax call. Because UI Dialog moved the long list out of the container it was Ajaxed into and stuck it at the end of the HTML body, when I request a new list, I end up with two divs with the same ID, each containing a different long list -- one in the Ajax container, and one at the end of the body. The most correct way I see to handle this is to first completely destroy the old long list before Ajaxing a new one. (One could also check for UI Dialog objects and move the long list in code but that is cumbersome and may also lose div attributes.)

In testing (jQuery 1.4.4, UI 1.8.10), I found that .dialog("destroy") on the original div works exactly the same as .remove() on the UI Dialog parent div. That is, only the UI Dialog wrapper divs are stripped away, and the original div is left behind in its original state. In other words, each of the following does the same thing [note: .empty() had no noticeable effect]:

// Three different ways to destroy just the UI Dialog
// (and leave the original div).
$(".ui-dialog:has(#myDialog)").remove();
$("#myDialog").parents(".ui-dialog").remove();
$("#myDialog").dialog("destroy");

Thus, the best way to destroy both the UI Dialog wrapper AND the original div appears to be this:

// Remove the old dialog and div to make way for a new one via Ajax.
$("#myDialog").dialog("destroy");
$("#myDialog").remove();

If you want to be sure you destroy all copies -- in case you accidentally create too many with too many calls to .dialog() -- you need something in front of the #id selector, such as:

// Remove all old dialogs and divs to make way for a new one via Ajax.
$("div#myDialog").dialog("destroy");
$("div#myDialog").remove();

You could do this in one line but it is less apparent what your intent is:

// Remove all old dialogs and divs to make way for a new one via Ajax.
// This technique is not recommended.
$("div#myDialog").parents(".ui-dialog").andSelf().remove();

I tested all of this in FF and some of it in IE8.


Firs check the dialog is already exist then destroy that one and re-initilaze dialog on rendering
if ($("#dialogId").hasClass('ui-dialog-content')) {
      $('dialogId').dialog('destroy');
    }

    $("#dialogId").dialog({
      title: 'Warning',
      autoOpen: false,
      modal: true,
      width: 600,
      closeOnEscape: true,
      draggable: false,
      resizable: false,
    });
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜