JQuery对话框:如何进行部分页面刷新并每次都获得新的对话框

时间:2010-01-19 16:23:52

标签: jquery ajax jquery-ui dialog partial-page-refresh

在尝试创建对话框然后进行部分页面渲染时,我的JQuery对话框出现了工作流问题。我将尝试通过一个示例场景,并提前为长期问题描述道歉:

页面加载,我希望将html转换为JQuery对话框。对话框在document.ready上创建(使用.dialog()),但autoOpen属性设置为false。当JQuery创建对话框时(如果我使用Firebug来检查页面),对话框html实际上是从它的正常位置剥离并停留在文档的最末端,周围有一些包装类。用户通过单击仅执行$dialogDiv.dialog('open')

的链接打开对话框

所以一切正常。问题是我有时会使用AJAX(使用ASP.NET MVC RenderPartial)进行部分页面重新加载。我正在刷新的页面部分恰好包含了所有的对话框html,因此会重新写出来。但请记住,对话框(包含所有JQuery包装类等)已经存在于文档的底部。那个html不是页面刷新的一部分,所以现在我坚持使用两组对话框html。这给了我各种各样的问题,因为我在页面上有重复的id,并且这些html元素上的jQuery行为变得不可预测。当我开始进行3,4,5个部分页面刷新时,情况会更糟,因为那时我有3个,4个,5个对话框html(在document.ready上只有一个真正的对话框)。

我想我可能需要在某些时候破坏对话框或某些东西,但我对这种方法没有任何好运。有没有人有任何想法?

非常感谢。

3 个答案:

答案 0 :(得分:7)

根据the docs销毁对话框删除对话框功能并将其恢复到初始化前状态,但不会将其从DOM中删除。

由于您要替换内容和对话框,您可以删除旧内容。

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

回复您的评论

我没有看到你的代码,所以我不确定你是如何设置对话框的,但是从一般意义上来说,我只使用将被替换的对话框来填充变量。

//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();
  });
}

答案 1 :(得分:0)

在解决了这个问题和之前给出的答案后,我发现答案中缺少一些重要的细节。这里最重要的一点是,虽然.dialog("destroy")确实将div恢复到其pre-init状态,但它不会将div恢复到DOM中的原始位置。 (BAHDev的问题提到UI对话框首先如何移动div。)这对于Ajax操作至关重要,并且应该在jQuery文档中明确这个div位置的更改/不更改(这样可以节省很多时间)。

如果Ajax只对象div的内容,那么这种行为可能并不重要,因为你可以轻松地找到并重写div内容,无论它位于DOM中的哪个位置。但是,如果您的对话框内容与其他对象一起内联Ajax,那么从原始位置移动div可能会导致后来的Ajaxing在原始位置创建另一个div,从而导致多个具有相同ID的div。

例如,我在一次Ajax调用中请求了一个简短的产品列表和一长串产品。短列表进入屏幕,长列表进入隐藏对话框。因为列表是相关的,所以在一次Ajax调用中抓取它们是有意义的。因为UI Dialog将长列表移出容器,所以它被Ajax加入并粘贴在HTML主体的末尾,当我请求一个新列表时,我最终得到两个具有相同ID的div,每个div包含一个不同的长列表 - 一个在Ajax容器中,一个在主体末端。我认为处理这个问题最正确的方法是在Ajaxing一个新列表之前首先彻底销毁旧的长列表。 (也可以检查UI Dialog对象并在代码中移动长列表,但这很麻烦,也可能会丢失div属性。)

在测试(jQuery 1.4.4,UI 1.8.10)中,我发现原始div上的.dialog("destroy")与UI Dialog父div上的.remove()完全相同。也就是说,只有UI Dialog包装器div被剥离,并且原始div被保留在其原始状态。换句话说,以下每个都做同样的事情[注意:.empty()没有明显的效果]:

// 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");

因此,销毁UI Dialog包装器和原始div的最佳方法似乎是:

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

如果您想确保销毁所有副本 - 如果您不小心创建了太多而且调用.dialog()的次数过多 - 您需要在#id选择器前面添加一些内容,例如:

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

您可以在一行中执行此操作,但不太明显您的意图:

// 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();

我在FF中测试了所有这些,在IE8中测试了一些。

答案 2 :(得分:0)

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,
    });