Twitter modal remoto bootstrap mostra lo stesso contenuto ogni volta


263

Sto usando il bootstrap di Twitter, ho specificato un modale

<div class="modal hide" id="modal-item">

    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">x</button>
        <h3>Update Item</h3>
    </div>

    <form action="http://www.website.com/update" method="POST" class="form-horizontal">

    <div class="modal-body">
        Loading content...
    </div>

    <div class="modal-footer">
        <a href="#" class="btn" data-dismiss="modal">Close</a>
        <button class="btn btn-primary" type="submit">Update Item</button>
    </div>

    </form>

</div>

E i collegamenti

<a href="http://www.website.com/item/1" data-target="#modal-item" data-toggle="modal">Edit 1</a>
<a href="http://www.website.com/item/2" data-target="#modal-item" data-toggle="modal">Edit 2</a>
<a href="http://www.website.com/item/3" data-target="#modal-item" data-toggle="modal">Edit 2</a>

Quando clicco su uno di questi link per la prima volta, vedo il contenuto corretto, ma quando faccio clic su altri link mostra lo stesso contenuto caricato per la prima volta, non aggiorna il contenuto.

Voglio che venga aggiornato ogni volta che viene cliccato.

PS: Posso facilmente farlo funzionare tramite la funzione jQuery personalizzata, ma voglio sapere se è possibile con la funzione remota modale Bootstrap nativa, poiché dovrebbe essere abbastanza semplice e immagino che sto solo complicando le cose.


Stessa correzione, ma modificata per Bootstrap 3. Bootstrap 3 introduce gli spazi dei nomi. plnkr.co/edit/HWSgSw?p=preview
Jeff H

Risposte:


447

Il problema è duplice.

Innanzitutto , una volta che un oggetto Modal viene istanziato, viene permanentemente associato all'elemento specificato da data-targete successive chiamate per mostrare che il modale lo chiamerà solo toggle(), ma non aggiornerà i valori in options. Pertanto, anche se gli hrefattributi sono diversi nei diversi collegamenti, quando il modale viene attivato, il valore per remotenon viene aggiornato. Per la maggior parte delle opzioni, si può aggirare questo problema modificando direttamente l'oggetto. Per esempio:

$('#myModal').data('bs.modal').options.remote = "http://website.com/item/7";

Tuttavia, in questo caso non funzionerà, perché ...

In secondo luogo , il plug-in Modal è progettato per caricare la risorsa remota nel costruttore dell'oggetto Modal, il che purtroppo significa che anche se viene apportata una modifica al options.remote, non verrà mai ricaricato .

Un semplice rimedio è quello di distruggere l'oggetto modale prima dei successivi toggle. Un'opzione è semplicemente distruggerlo dopo aver finito di nascondersi:

$('body').on('hidden.bs.modal', '.modal', function () {
  $(this).removeData('bs.modal');
});

Nota: regolare i selettori in base alle esigenze. Questo è il più generale.

Plunker

Oppure potresti provare a elaborare uno schema più complicato per fare qualcosa come verificare se il collegamento che avvia il modale è diverso dal precedente. Se lo è, distruggi; in caso contrario, non è necessario ricaricare.


1
@VladimirStarkov Mi dispiace, sembra che abbia dimenticato la hideclasse sul modale, quindi se la tua finestra era troppo piccola, il modale potrebbe aver bloccato gli eventi del mouse sui pulsanti. Per qualche motivo JSFiddle.net è davvero brutto questa mattina (ho avuto un 504 che cercava di aggiornare), quindi ho appena rifatto l'esempio su plnkr.co, che è comunque meglio per AJAX.
Merv

3
c'è un altro problema: il .modal-body avrà ancora il testo, quindi ho aggiunto: <CODE> $ ('# myModal .modal-body'). text ("Loading ...") </CODE> nel listener di eventi nascosto
rbp

5
bs.modalha $(this).removeData('bs.modal')funzionato per me con Bootstrap 3
jvannistelrooy il

2
Il codice di lavoro completo per Boostrap 3 è$('body').on('hidden.bs.modal', '.modal', function () { $(this).removeData('bs.modal'); });
Christophe Fondacci,

1
Vorrei anche verificare se il modal nascosto è caricato da una fonte remota, in modo da non interrompere i modali con contenuto statico: var modalData = $(this).data('bs.modal'); if (modalData && modalData.options.remote)...
Wojtek Kruszewski

171

Per bootstrap 3 dovresti usare:

$('body').on('hidden.bs.modal', '.modal', function () {
    $(this).removeData('bs.modal');
});

17
Mio eroe. Adoro questi cambiamenti senza documenti.
Jorin,

2
Questo ha aiutato molto. Bootstrap 3 non è compatibile con le versioni precedenti e la maggior parte dei contenuti su SO (o altri forum) riguarda BS <3, provare queste soluzioni fa perdere molto tempo.
Swapnil,

7
Non perfetto: mostra brevemente il vecchio contenuto prima del nuovo contenuto.
Laurent,

3
Se vuoi svuotare il modale usando l'esempio sopra, dovresti essere in grado di aggiungere quanto segue prima o dopo la remoteDatariga:$(this).empty()
jgillman,

11
Non dovresti usare $(this).empty(). L' remoteopzione carica i dati remoti nell'elemento nidificato <div class="modal-content">. Usa $('.modal-content', this).empty();invece.
Gavin,

50

Per Bootstrap 3.1 ti consigliamo di rimuovere i dati e svuotare la modal-contentfinestra anziché l'intera finestra di dialogo (3.0) per evitare lo sfarfallio durante l'attesa del caricamento del contenuto remoto.

$(document).on("hidden.bs.modal", function (e) {
    $(e.target).removeData("bs.modal").find(".modal-content").empty();
});

Se stai utilizzando modali non remoti, il codice sopra rimuoverà, ovviamente, il loro contenuto una volta chiuso (non valido). Potrebbe essere necessario aggiungere qualcosa a quei modali (come una .local-modalclasse) in modo che non siano interessati. Quindi modificare il codice sopra per:

$(document).on("hidden.bs.modal", ".modal:not(.local-modal)", function (e) {
    $(e.target).removeData("bs.modal").find(".modal-content").empty();
});

Nelle pagine remote assicurati di non caricare bootstrap o librerie jquery. Ucciderà qualsiasi riferimento e ti lascerà vuoto con un modale vuoto.
Bankzilla,

Questo non funzionava per me. Ecco il mio codice che funziona: $ (document) .on ("hidden.bs.modal", ".modal", function (e) {if (! $ (E.target) .is (". Local-modal ")) {$ (e.target) .removeData (" bs.modal "). find (". modal-content "). empty ();}});
Kevin,

Quando uso $(e.target).removeData("bs.modal").find(".modal-content").empty();è come se il mio modale venisse in qualche modo nascosto e apparisse solo la sovrapposizione grigia.
Axel

30

Grazie Merv. Ho iniziato a armeggiare con boostrap.js ma la tua risposta è una soluzione rapida e pulita. Ecco cosa ho finito per usare nel mio codice.

$('#modal-item').on('hidden', function() {
    $(this).removeData('modal');
});

21

La risposta accettata non ha funzionato per me, quindi sono andato con JavaScript per farlo.

<a href="/foo" class="modal-link">
<a href="/bar" class="modal-link">

<script>
$(function() {
    $(".modal-link").click(function(event) {
        event.preventDefault()
        $('#myModal').removeData("modal")
        $('#myModal').modal({remote: $(this).attr("href")})
    })
})

14

Funziona con Bootstrap 3 FYI

$('#myModal').on('hidden.bs.modal', function () {
  $(this).removeData('bs.modal');
});

7

Il mio progetto è integrato in Yii e utilizza il plug-in Bootstrap-Yii, quindi questa risposta è rilevante solo se si utilizza Yii.

La correzione di cui sopra ha funzionato, ma solo dopo la prima volta è stato mostrato il modale. La prima volta è venuto vuoto. Penso che sia perché dopo la mia iniziazione del codice Yii chiama la funzione hide del modale cancellando così le mie variabili di iniziazione.

Ho scoperto che mettere la chiamata removeData immediatamente prima del codice che ha lanciato il modale ha funzionato. Quindi il mio codice è strutturato in questo modo ...

$ ("#myModal").removeData ('modal');
$ ('#myModal').modal ({remote : 'path_to_remote'});

5

In Bootstrap 3.2.0 l'evento "on" deve trovarsi sul documento e devi svuotare il modale:

$(document).on("hidden.bs.modal", function (e) {
    $(e.target).removeData("bs.modal").find(".modal-content").empty();
});

In Bootstrap 3.1.0 l'evento "on" può trovarsi sul corpo:

$('body').on('hidden.bs.modal', '.modal', function () {
    $(this).removeData('bs.modal');
});

La soluzione 3.2 è stata l'unica cosa che ha funzionato correttamente per me in Bootstrap 3.1 - usando l'approccio body, alcuni dei miei eventi su modale sono stati sganciati.
StuartQ,

3

Perché non renderlo più generale con BS 3? Usa "[qualcosa] modale" come ID del DIV modale.

$("div[id$='modal']").on('hidden.bs.modal',
    function () {
        $(this).removeData('bs.modal');
    }
);

2

L'unica opzione di lavoro per me è:

$('body').on('hidden.bs.modal', '#modalBox', function () {
    $(this).remove();
});

Uso Bootstrap 3 e ho una funzione chiamata popup('popup content') che aggiunge la modal box html.


2
questa è l'unica cosa che ha funzionato per me con BS 3.3.6. anche usando il modello di manubrio. Suggerisco comunque di usare il documento anziché il corpo.
Dbinott,

1

Aggiunta di $ (this) .html (''); per cancellare anche i dati visibili e funziona abbastanza bene


1

Se viene fornito un URL remoto, il contenuto verrà caricato una volta tramite il metodo di caricamento di jQuery e iniettato nel div .modal-content. Se stai usando l'API dei dati, puoi in alternativa utilizzare l'attributo href per specificare l'origine remota. Un esempio di questo è mostrato di seguito

$.ajaxSetup ({
    // Disable caching of AJAX responses
    cache: false
});

1

Ho aggiunto qualcosa del genere, perché il contenuto più vecchio viene mostrato fino a quando non appare quello nuovo, con .html ('') all'interno del contenuto .modal cancella l'HTML all'interno, spero che aiuti

$('#myModal').on('hidden.bs.modal', function () {
   $('#myModal').removeData('bs.modal');
   $('#myModal').find('.modal-content').html('');
});

Questa è di gran lunga la risposta di lavoro più semplice che ho trovato. Niente di complicato nella risposta, poche righe di codice e facile da interpretare. Ha funzionato perfettamente la prima volta senza scherzare con esso.
Tarquinio,

0

Ho scritto un semplice frammento gestendo l'aggiornamento del modale. Fondamentalmente memorizza il link cliccato nei dati modali e controlla se è lo stesso link che è stato cliccato, rimuovendo o meno i dati modali.

var handleModal = function()
{
    $('.triggeringLink').click(function(event) {
        var $logsModal = $('#logsModal');
        var $triggeringLink = $logsModal.data('triggeringLink');

        event.preventDefault();

        if ($logsModal.data('modal') != undefined
            && $triggeringLink != undefined
            && !$triggeringLink.is($(this))
        ) {
            $logsModal.removeData('modal');
        }

        $logsModal.data('triggeringLink', $(this));

        $logsModal.modal({ remote: $(this).attr('href') });
        $logsModal.modal('show');
    });
};

0

Per Bootstrap 3, in modal.js ho cambiato:

$(document)
  .on('show.bs.modal',  '.modal', function () { $(document.body).addClass('modal-open') })
  .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open'); })

per

$(document)
  .on('show.bs.modal',  '.modal', function () { $(document.body).addClass('modal-open') })
  .on('hidden.bs.modal', '.modal', function () { 
    $(this).removeData('bs.modal').empty()
    $(document.body).removeClass('modal-open')
  })

(spazio extra aggiunto per maggiore chiarezza)

Questo impedisce qualsiasi flash indesiderato di vecchio contenuto modale chiamando empty () sul contenitore modale e rimuovendo i dati.


0
        $('#myModal').on('hidden.bs.modal', function () {
            $(this).removeData('modal');
        });

Questo funziona per me.


0

Questo altro approccio funziona bene per me:

$("#myModal").on("show.bs.modal", function(e) {
    var link = $(e.relatedTarget);
    $(this).find(".modal-body").load(link.attr("href"));
});

0
$('body').on('hidden.bs.modal', '.modal', function () {
       $("#mention Id here what you showed inside modal body").empty()
});

Quale elemento HTML vuoi svuotare (div, span qualunque).


0

Questo funziona per me:

modale

<div class="modal fade" id="searchKaryawan" tabindex="-1" role="dialog" aria-labelledby="SearchKaryawanLabel" aria-hidden="true"> <div class="modal-dialog">
<div class="modal-content">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    <h4 class="modal-title" id="SearchKaryawanLabel">Cari Karyawan</h4>
  </div>
  <div class="modal-body">
    <input type="hidden" name="location">
    <input name="cariNama" type="text" class="form-control" onkeyup="if (this.value.length > 3) cariNikNama();" />
    <div class="links-area" id="links-area"></div>
  </div>
  <div class="modal-footer">
  </div>
</div> </div></div>

copione

<script type="text/javascript">$('body').on('hidden.bs.modal', '.modal', function () {  $(".links-area").empty() }); </script>

area dei collegamenti è l'area in cui ho messo i dati e ho bisogno di cancellare


0

Versione estesa della risposta accettata da @merv. Verifica inoltre se il caricamento modale è stato caricato da una fonte remota e cancella il vecchio contenuto per evitare che lampeggi.

$(document).on('hidden.bs.modal', '.modal', function () {
  var modalData = $(this).data('bs.modal');

  // Destroy modal if has remote source – don't want to destroy modals with static content.
  if (modalData && modalData.options.remote) {
    // Destroy component. Next time new component is created and loads fresh content
    $(this).removeData('bs.modal');
    // Also clear loaded content, otherwise it would flash before new one is loaded.
    $(this).find(".modal-content").empty();
  }
});

https://gist.github.com/WojtekKruszewski/ae86d7fb59879715ae1e6dd623f743c5


-1

Testato su Bootstrap versione 3.3.2

  $('#myModal').on('hide.bs.modal', function() {
    $(this).removeData();
  });

1
Questa è una soluzione terribile. Chiamare .removeData()senza parametri dirà a jquery di rimuovere tutti i dati associati a quell'elemento. Per quanto riguarda il problema del PO, .removeData('bs.modal')o .removeData('modal')sarebbe sufficiente ed è molto sicuro.
Julian Paolo Dayag,

-4

Buona fortuna con questo:

$('#myModal').on('hidden.bs.modal', function () {
    location.reload();
});

2
questo è inutile. ricaricare la pagina non è la soluzione.
Dbinott,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.