El modal remoto de arranque de Twitter muestra el mismo contenido cada vez

263

Estoy usando el programa de arranque de Twitter, he especificado un modal

<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>

Y los enlaces

<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>

Cuando hago clic en cualquiera de estos enlaces por primera vez, veo el contenido correcto, pero cuando hago clic en otros enlaces muestra el mismo contenido cargado por primera vez, no actualiza el contenido.

Quiero que se actualice cada vez que se hace clic.

PD: Puedo hacer que funcione fácilmente a través de la función jQuery personalizada, pero quiero saber si es posible con la función remota modal Bootstrap nativa, ya que debería ser lo suficientemente fácil y supongo que solo estoy complicando las cosas.

Dhruv Kumar Jha
fuente
La misma corrección, pero modificada para Bootstrap 3. Bootstrap 3 introduce espacios de nombres. plnkr.co/edit/HWSgSw?p=preview
Jeff H
55
Tenga en cuenta que los remotemodos están en desuso a partir de Bootstrap v3.2.1 y desaparecerán en v4.
cvrebert

Respuestas:

447

El problema es doble.

Primero , una vez que se crea una instancia de un objeto modal, se adjunta de forma persistente al elemento especificado por data-targety las llamadas posteriores para mostrar que modal solo lo invocará toggle(), pero no actualizará los valores en el options. Entonces, aunque los hrefatributos son diferentes en sus diferentes enlaces, cuando se alterna el modal, el valor de remoteno se actualiza. Para la mayoría de las opciones, se puede evitar esto editando directamente el objeto. Por ejemplo:

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

Sin embargo, eso no funcionará en este caso, porque ...

En segundo lugar , el complemento Modal está diseñado para cargar el recurso remoto en el constructor del objeto Modal, lo que desafortunadamente significa que incluso si se realiza un cambio en el options.remote, nunca se volverá a cargar .

Un remedio simple es destruir el objeto modal antes de alternarlo posteriormente. Una opción es simplemente destruirlo después de que termine de esconderse:

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

Nota: Ajuste los selectores según sea necesario. Este es el más general.

Saqueador

O podría intentar crear un esquema más complicado para hacer algo como verificar si el enlace que inicia el modal es diferente del anterior. Si es así, destruye; Si no es así, no es necesario volver a cargar.

merv
fuente
1
@VladimirStarkov Lo siento, parece que olvidé la hideclase en el modal, por lo que si su ventana era demasiado pequeña, el modal podría haber estado bloqueando los eventos del mouse en los botones. Por alguna razón, JSFiddle.net es realmente malo esta mañana (obtuve un 504 tratando de actualizar), así que simplemente rehice el ejemplo en plnkr.co, que de todos modos es mejor para AJAX.
merv
3
hay otro problema: el .modal-body todavía tendrá el texto, así que agregué: <CODE> $ ('# myModal .modal-body'). text ("Cargando ...") </CODE> en el oyente oculto del evento
rbp
55
bs.modalen el $(this).removeData('bs.modal')trabajado para mí con Bootstrap 3
jvannistelrooy
2
El código de trabajo completo para Boostrap 3 es$('body').on('hidden.bs.modal', '.modal', function () { $(this).removeData('bs.modal'); });
Christophe Fondacci
1
También verificaría si el modo oculto se carga desde una fuente remota, para no romper los modales con contenido estático: var modalData = $(this).data('bs.modal'); if (modalData && modalData.options.remote)...
Wojtek Kruszewski
171

Para bootstrap 3 debes usar:

$('body').on('hidden.bs.modal', '.modal', function () {
    $(this).removeData('bs.modal');
});
Camilo Nova
fuente
17
Mi héroe. Me encantan estos cambios indocumentados.
Jorin
2
Esto ayudó mucho. Bootstrap 3 no es compatible con versiones anteriores y la mayor parte del contenido de SO (u otros foros) se trata de BS <3, probar esas soluciones desperdicia mucho tiempo.
Swapnil
77
No perfecto: muestra brevemente el contenido anterior antes del contenido nuevo.
Laurent
3
Si desea vaciar el modal utilizando el ejemplo anterior, debería poder agregar lo siguiente antes o después de la remoteDatalínea:$(this).empty()
jgillman
11
No deberías usar $(this).empty(). La remoteopción carga los datos remotos en el <div class="modal-content">elemento anidado . Usar en su $('.modal-content', this).empty();lugar.
Gavin
50

Para Bootstrap 3.1, querrá eliminar datos y vaciar el modal-contentcuadro de diálogo en lugar de todo (3.0) para evitar el parpadeo mientras espera que se cargue el contenido remoto.

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

Si está utilizando modales no remotos, el código anterior eliminará, por supuesto, su contenido una vez cerrado (incorrecto). Es posible que deba agregar algo a esos modales (como una .local-modalclase) para que no se vean afectados. Luego modifique el código anterior para:

$(document).on("hidden.bs.modal", ".modal:not(.local-modal)", function (e) {
    $(e.target).removeData("bs.modal").find(".modal-content").empty();
});
slopapa
fuente
En las páginas remotas, asegúrese de no cargar bootstrap o bibliotecas jquery. Eliminará cualquier referencia y te dejará vacío y modal vacío.
Bankzilla
Esto no estaba funcionando para mí. Aquí está mi código que funciona: $ (document) .on ("hidden.bs.modal", ".modal", function (e) {if (! $ (E.target) .is (". Local-modal ")) {$ (e.target) .removeData (" bs.modal "). find (". modal-content "). empty ();}});
Kevin
Cuando lo uso $(e.target).removeData("bs.modal").find(".modal-content").empty();, es como si mi modal se ocultara de alguna manera y solo aparece la superposición gris.
Axel
30

Gracias merv. Comencé a jugar boostrap.js pero su respuesta es una solución rápida y limpia. Esto es lo que terminé usando en mi código.

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

La respuesta aceptada no funcionó para mí, así que utilicé JavaScript para hacerlo.

<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")})
    })
})
James Ward
fuente
14

Esto funciona con Bootstrap 3 FYI

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

Mi proyecto está construido en Yii y usa el complemento Bootstrap-Yii, por lo que esta respuesta solo es relevante si está usando Yii.

La corrección anterior funcionó, pero solo después de la primera vez que se mostró el modal. La primera vez que salió vacío. Creo que es porque después de mi iniciación del código, Yii llama a la función hide del modal, borrando así mis variables de iniciación.

Descubrí que poner la llamada removeData inmediatamente antes del código que lanzó el modal hizo el truco. Entonces mi código está estructurado así ...

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

En Bootstrap 3.2.0 el evento "on" debe estar en el documento y debe vaciar el modal:

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

En Bootstrap 3.1.0 el evento "on" puede estar en el cuerpo:

$('body').on('hidden.bs.modal', '.modal', function () {
    $(this).removeData('bs.modal');
});
Romain
fuente
La solución 3.2 fue lo único que funcionó correctamente para mí en Bootstrap 3.1: al usar el enfoque corporal, algunos de mis eventos en modal se desengancharon.
StuartQ
3

¿Por qué no hacerlo más general con BS 3? Simplemente use "[algo] modal" como la ID del DIV modal.

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

La única opción de trabajo para mí es:

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

Uso Bootstrap 3 y tengo una función llamada popup('popup content') que agrega el cuadro modal html.

Orkun Tuzel
fuente
2
Esto es lo único que me funcionó con BS 3.3.6. también usando plantilla de manillar. Sin embargo, sugiero usar el documento en lugar del cuerpo.
dbinott
1

Agregar un $ (this) .html (''); para borrar datos visibles también, y funciona bastante bien

webstr
fuente
1

Si se proporciona una URL remota, el contenido se cargará una vez mediante el método de carga de jQuery y se inyectará en el div .modal-content. Si está utilizando la API de datos, también puede utilizar el atributo href para especificar la fuente remota. Un ejemplo de esto se muestra a continuación.

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

He agregado algo como esto, porque el contenido anterior se muestra hasta que aparece el nuevo, con .html ('') dentro del contenido .modal borrará el HTML dentro, espero que ayude

$('#myModal').on('hidden.bs.modal', function () {
   $('#myModal').removeData('bs.modal');
   $('#myModal').find('.modal-content').html('');
});
Mau GM
fuente
Esta es, con mucho, la respuesta funcional más simple que he encontrado. Nada complicado sobre la respuesta, pocas líneas de código y fácil de interpretar. Funcionó perfectamente la primera vez jugando con eso.
Tarquin
0

Escribí un fragmento simple manejando la actualización del modal. Básicamente, almacena el enlace en el que se hizo clic en los datos modales y verifica si es el mismo enlace en el que se ha hecho clic, eliminando o no los datos modales.

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');
    });
};
DevAntoine
fuente
0

Para Bootstrap 3, en modal.js cambié:

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

a

$(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')
  })

(espacio adicional agregado para mayor claridad)

Esto evita cualquier destello no deseado de contenido modal antiguo llamando a empty () en el contenedor modal y eliminando los datos.

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

Esta funciona para mí.

Shawn Ang
fuente
0

Este otro enfoque funciona bien para mí:

$("#myModal").on("show.bs.modal", function(e) {
    var link = $(e.relatedTarget);
    $(this).find(".modal-body").load(link.attr("href"));
});
Rhys Stephens
fuente
0
$('body').on('hidden.bs.modal', '.modal', function () {
       $("#mention Id here what you showed inside modal body").empty()
});

Qué elemento html desea vaciar (div, span lo que sea).

Atul
fuente
0

Esta funciona para mí:

modal

<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>

guión

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

área de enlaces es el área donde pongo los datos y necesito borrar

dewaz
fuente
0

Versión ampliada de la respuesta aceptada por @merv. También verifica si el modo oculto se carga desde la fuente remota y borra el contenido antiguo para evitar que parpadee.

$(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

Wojtek Kruszewski
fuente
-1

Probado en Bootstrap versión 3.3.2

  $('#myModal').on('hide.bs.modal', function() {
    $(this).removeData();
  });
Abudayah
fuente
1
Esta es una solución terrible. Llamar .removeData()sin parámetros le dirá a jquery que elimine todos los datos adjuntos a ese elemento. En lo que respecta al problema del OP, .removeData('bs.modal')o .removeData('modal')sería suficiente y es muy seguro.
Julian Paolo Dayag
-4

Buena suerte con este:

$('#myModal').on('hidden.bs.modal', function () {
    location.reload();
});
Mappy
fuente
2
Esto es inútil. Recargar la página no es la solución.
dbinott