2010-01-19 9 views
9

Si verifica un problema di flusso di lavoro con le finestre di dialogo JQuery quando si tenta di creare le finestre di dialogo e quindi di eseguire il rendering di una pagina parziale. Proverò a passare attraverso uno scenario di esempio e mi scuso in anticipo per la descrizione del problema lungo:Finestra di dialogo JQuery: come eseguire un aggiornamento parziale della pagina e ottenere ogni volta nuove finestre di dialogo

Viene caricata la pagina, con l'html che vorrei essere trasformato in finestre di dialogo JQuery. Le finestre di dialogo vengono create su document.ready (utilizzando .dialog()), ma la proprietà autoOpen è impostata su false. Quando JQuery crea le finestre di dialogo (se sto usando Firebug per ispezionare la pagina), la finestra di dialogo html viene effettivamente rimossa dalla sua posizione normale e bloccata alla fine del documento, con alcune classi wrapper attorno ad essa. L'utente apre le finestre di dialogo facendo clic su un collegamento che fa appena un $dialogDiv.dialog('open').

In modo che tutto funzioni correttamente. Il problema è che ci sono delle volte in cui eseguo una ricarica parziale della pagina usando AJAX (usando ASP.NET MVC RenderPartial). La parte della pagina che sto aggiornando sembra avere tutta la finestra di dialogo in esso contenuta, in modo che venga riscritta. Ma ricorda che la finestra di dialogo (con tutte le classi wrapper JQuery, ecc.) È già presente nella parte inferiore del documento. Quel html non faceva parte dell'aggiornamento della pagina, quindi ora sono bloccato con due gruppi di finestre di dialogo html. Questo mi dà tutti i tipi di problemi perché ho degli id ​​duplicati sulla pagina e il comportamento di jQuery su questi elementi HTML diventa imprevedibile. È ancora peggio quando comincio a fare 3, 4, 5 aggiornamenti di pagine parziali, perché poi ho 3, 4, 5 set di finestre di dialogo html (con solo una vera finestra di dialogo creata su document.ready).

Sto pensando che a un certo punto potrei aver bisogno di distruggere i dialoghi o qualcosa del genere, ma non ho avuto fortuna con questo approccio. Qualcuno ha qualche idea?

Grazie mille.

risposta

7

In base a the docs, la distruzione di una finestra di dialogo rimuove la funzionalità di dialogo e la ripristina allo stato pre-init ma non la rimuove dal DOM.

Poiché si sta sostituendo il contenuto e la finestra di dialogo, è possibile rimuovere solo quelli vecchi.

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

In risposta a voi commentare

non ho visto te codice, quindi non sono esattamente sicuro di come sei impostazioni su per le finestre di dialogo, ma in senso generale avrei popolare una variabile con solo le finestre di dialogo che verranno sostituite.

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

@czarchaic, Grazie per la risposta. Potresti essere l'unica persona che ha avuto il tempo di leggere tutta la domanda. Una domanda di follow-up, però .. Ho finestre di dialogo come errori e finestre di avviso che non vorrei eliminare. Questi verrebbero svuotati e cancellati usando il metodo che hai dato. Osservando le finestre di dialogo create da JQuery, esso fornisce al wrapper esterno lo stesso elenco di classi su ognuna, che è 'ui-dialog ui-widget ui-widget-content ui-corner-all ui-draggable'. Come posso specificare quali finestre di dialogo svuotare e rimuovere e quali no? Grazie ancora. – BAHDev

+0

@BAHDev. Aggiornerò il mio post – czarchaic

0

Dopo aver risolto questo problema e ottenuto la risposta precedente, ho scoperto alcuni dettagli importanti mancanti nella risposta. Il punto più importante qui è che mentre .dialog("destroy") ripristina il div al suo stato pre-init, NON ripristina il div nella posizione originale nel DOM. (La domanda di BAHDev menziona come UI Dialog sposta il div in primo luogo.) Questo è fondamentale per l'operazione Ajax e questo cambiamento/non cambiamento della posizione div dovrebbe essere chiarito nella documentazione di jQuery (che mi avrebbe salvato un sacco di tempo).

Se si assegna solo il contenuto della finestra di dialogo div, allora questo comportamento probabilmente non è critico in quanto si può facilmente trovare e riscrivere il contenuto div indipendentemente da dove risiede nel DOM. Se il contenuto della finestra di dialogo ottiene Ajaxed in linea con altri oggetti, tuttavia, spostare un div dalla posizione originale probabilmente causerà successivamente Ajaxing per creare un altro div nella posizione originale risultante in più div dello stesso ID.

Ad esempio, richiedo un breve elenco di prodotti e un lungo elenco di prodotti in una chiamata Ajax.La short list va alla schermata e la lunga lista va in una finestra nascosta. Poiché le liste sono correlate, ha senso prenderle entrambe in una sola chiamata Ajax. Poiché la finestra di dialogo dell'interfaccia utente ha spostato la lunga lista fuori dal contenitore in cui si trovava Ajax e l'ha bloccata alla fine del corpo HTML, quando richiedo un nuovo elenco, ottengo due div con lo stesso ID, ciascuno contenente un elenco lungo diverso - Uno nel contenitore Ajax e uno nella parte finale del corpo. Il modo più corretto che vedo per gestirlo è quello di distruggere completamente la vecchia lunga lista prima di trasferirne una nuova. (Si potrebbe anche verificare la presenza di oggetti UI Dialog e spostare l'elenco lungo nel codice ma è ingombrante e potrebbe anche perdere attributi div.)

In testing (jQuery 1.4.4, UI 1.8.10), ho trovato che .dialog("destroy") sul div originale funziona esattamente come .remove() sul div genitore Dialogo UI. Cioè, solo i div del wrapper Dialog dell'interfaccia utente vengono rimossi, e il div originale viene lasciato indietro nel suo stato originale. In altre parole, ciascuno dei seguenti fa la stessa cosa [nota: .empty() ha avuto alcun effetto evidente]:

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

Così, il modo migliore per distruggere sia l'involucro UI Dialog e il div originale sembra essere questo:

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

Se si vuole essere sicuri di distruggere tutte le copie - nel caso in cui si creano accidentalmente troppe con troppe chiamate a .dialog() - avete bisogno di qualcosa di fronte al selettore di #id, come ad esempio :

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

Si potrebbe fare questo in una sola riga, ma è meno evidente ciò che il vostro intento è:

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

ho provato tutto questo in FF e alcuni di essi in IE8.

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