O modal remoto de inicialização do Twitter mostra o mesmo conteúdo sempre


263

Estou usando a inicialização do Twitter, especifiquei um 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>

E os links

<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 clico em um desses links pela primeira vez, vejo o conteúdo correto, mas quando clico em outros links, ele mostra o mesmo conteúdo carregado pela primeira vez e não atualiza o conteúdo.

Quero que ele seja atualizado sempre que clicar.

PS: Eu posso fazê-lo funcionar facilmente através da função jQuery personalizada, mas quero saber se é possível com a função remota modal Bootstrap nativa, pois deve ser fácil o suficiente e acho que estou apenas complicando as coisas.


Mesma correção, mas modificada para o Bootstrap 3. O Bootstrap 3 apresenta espaços para nome. plnkr.co/edit/HWSgSw?p=preview
Jeff H

Respostas:


447

O problema é duplo.

Primeiro , uma vez que um objeto Modal é instanciado, ele é persistentemente anexado ao elemento especificado por data-targete chamadas subseqüentes para mostrar que o modal apenas o chamará toggle(), mas não atualizará os valores no options. Portanto, mesmo que os hrefatributos sejam diferentes nos seus links diferentes, quando o modal é alternado, o valor para remotenão está sendo atualizado. Para a maioria das opções, é possível contornar isso editando diretamente o objeto. Por exemplo:

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

No entanto, isso não funcionará neste caso, porque ...

Segundo , o plug-in Modal foi projetado para carregar o recurso remoto no construtor do objeto Modal, o que infelizmente significa que, mesmo que seja feita uma alteração no options.remote, ele nunca será recarregado .

Um remédio simples é destruir o objeto Modal antes de alternar subseqüentemente. Uma opção é destruí-lo depois que ele se esconder:

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

Nota: Ajuste os seletores conforme necessário. Este é o mais geral.

Plunker

Ou você pode tentar criar um esquema mais complicado para fazer algo como verificar se o link que inicia o modal é diferente do anterior. Se for, destrua; se não for, não será necessário recarregar.


1
@ VladimirStarkov Desculpe por isso - parece que eu esqueci a hideclasse no modal, portanto, se sua janela era muito pequena, o modal pode estar bloqueando os eventos do mouse nos botões. Por alguma razão, o JSFiddle.net está muito ruim esta manhã (tenho um 504 tentando atualizar), então eu apenas refiz o exemplo no plnkr.co, que é melhor para o AJAX de qualquer maneira.
merv

3
há outro problema: o .modal-body ainda terá o texto, então eu adicionei: <CODE> $ ('# myModal .modal-body'). text ("Loading ...") </CODE> no ouvinte evento escondido
rbp

5
bs.modalem $(this).removeData('bs.modal')funcionou para mim com o Bootstrap 3
jvannistelrooy

2
Código de trabalho completo para Boostrap 3 é$('body').on('hidden.bs.modal', '.modal', function () { $(this).removeData('bs.modal'); });
Christophe Fondacci

1
Também gostaria de verificar se ser modal escondido é carregado de origem remota, de modo a não quebrar modais com conteúdo estático: var modalData = $(this).data('bs.modal'); if (modalData && modalData.options.remote)...
Wojtek Kruszewski

171

Para o bootstrap 3, você deve usar:

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

17
Meu heroi. Adoro essas mudanças não documentadas.
11133 Jorin

2
Isso ajudou muito. O Bootstrap 3 não é compatível com versões anteriores e a maior parte do conteúdo do SO (ou de outros fóruns) é sobre BS <3, tentar essas soluções gasta muito tempo.
precisa saber é o seguinte

7
Não é perfeito: mostra brevemente o conteúdo antigo antes do novo conteúdo.
Laurent

3
Se você deseja esvaziar o modal usando o exemplo acima, você deve ser capaz de adicionar o seguinte antes ou depois da remoteDatalinha:$(this).empty()
jgillman

11
Você não deveria usar $(this).empty(). A remoteopção carrega os dados remotos no <div class="modal-content">elemento aninhado . Use em $('.modal-content', this).empty();vez disso.
Gavin

50

No Bootstrap 3.1, você deseja remover os dados e esvaziar a modal-contentcaixa de diálogo (e não toda) (3.0) para evitar oscilações enquanto aguarda o carregamento do conteúdo remoto.

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

Se você estiver usando modais não remotos, o código acima removerá o conteúdo assim que estiver fechado (incorreto). Pode ser necessário adicionar algo a esses modais (como uma .local-modalclasse) para que eles não sejam afetados. Modifique o código acima para:

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

Nas páginas remotas, verifique se você não está carregando as bibliotecas de inicialização ou jquery. Isso mata qualquer referência e deixa você com um modal vazio.
Bankzilla

Isso não estava funcionando para mim. Aqui está o meu código que está funcionando: $ (document) .on ("hidden.bs.modal", ".modal", função (e) {if (! $ (E.target) .is (". Local-modal ")) {$ (e.target) .removeData (" bs.modal "). find (". modal-content "). empty ();}});
Kevin

Quando eu uso $(e.target).removeData("bs.modal").find(".modal-content").empty();, é como se meu modal estivesse oculto e apenas a sobreposição cinza fosse exibida.
Axel

30

Graças merv. Comecei a mexer no boostrap.js, mas sua resposta é uma solução rápida e limpa. Aqui está o que eu acabei usando no meu código.

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

21

A resposta aceita não funcionou para mim, então fui com o JavaScript para fazer isso.

<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

Isso funciona com o Bootstrap 3 FYI

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

7

Meu projeto é construído no Yii e usa o plug-in Bootstrap-Yii, portanto, essa resposta é relevante apenas se você estiver usando o Yii.

A correção acima funcionou, mas somente após a primeira vez que o modal foi mostrado. A primeira vez que apareceu vazia. Eu acho que é porque, após a iniciação do código, o Yii chama a função hide do modal, limpando assim minhas variáveis ​​de iniciação.

Descobri que colocar a chamada removeData imediatamente antes do código que iniciou o modal fez o truque. Então meu código está estruturado assim ...

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

5

No Bootstrap 3.2.0, o evento "on" deve estar no documento e você deve esvaziar o modal:

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

No Bootstrap 3.1.0, o evento "on" pode estar no corpo:

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

A solução 3.2 foi a única coisa que funcionou corretamente para mim no Bootstrap 3.1 - usando a abordagem do corpo, alguns dos meus eventos no modal tornaram-se desengatados.
StuartQ

3

Por que não torná-lo mais geral com o BS 3? Basta usar "[something] modal" como o ID do DIV modal.

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

2

A única opção de trabalho para mim é:

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

Eu uso o Bootstrap 3 e tenho uma função chamada popup('popup content') que acrescenta o html da caixa modal.


2
essa é a única coisa que funcionou para mim com o BS 3.3.6. também usando o modelo de guidão. Sugiro usar documento em vez de corpo no entanto.
dbinott

1

Adicionando um $ (this) .html (''); para limpar os dados visíveis também, e funciona muito bem


1

Se uma URL remota for fornecida, o conteúdo será carregado uma vez pelo método de carregamento do jQuery e injetado na div .modal-content. Se você estiver usando a API de dados, como alternativa, use o atributo href para especificar a fonte remota. Um exemplo disso é mostrado abaixo

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

1

Eu adicionei algo assim, porque o conteúdo mais antigo é mostrado até o novo, com .html ('') dentro do .modal-content limpará o HTML por dentro, espero que ajude

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

Esta é de longe a resposta mais simples que encontrei. Nada complicado na resposta, poucas linhas de código e fácil de interpretar. Funcionou perfeitamente primeira vez brincando com ele.
Tarquin 27/07

0

Eu escrevi um trecho simples lidando com a atualização do modal. Basicamente, ele armazena o link clicado nos dados do modal e verifica se é o mesmo link clicado, removendo ou não os dados modais.

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

Para o Bootstrap 3, no modal.js, mudei:

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

para

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

(espaçamento extra adicionado para maior clareza)

Isso evita qualquer flash indesejado do conteúdo modal antigo, chamando empty () no contêiner modal, além de remover os dados.


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

Este funciona para mim.


0

Essa outra abordagem funciona bem para mim:

$("#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()
});

Qual elemento html você deseja esvaziar como (div, abranja qualquer coisa).


0

Este funciona para mim:

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>

roteiro

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

área de links é a área onde eu coloco os dados e preciso limpar


0

Versão expandida da resposta aceita por @merv. Ele também verifica se o modal oculto está carregado da fonte remota e limpa o conteúdo antigo para impedir que ele pisque.

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

Testado no Bootstrap versão 3.3.2

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

1
Esta é uma solução terrível. Chamar .removeData()sem parâmetros informará o jquery para remover todos os dados anexados a esse elemento. No que diz respeito ao problema do OP, .removeData('bs.modal')ou .removeData('modal')seria suficiente e é muito seguro.
Julian Paolo Dayag

-4

Boa sorte com este:

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

2
isso é inútil. recarregar a página não é a solução.
dbinott
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.