Zdalny modal Twitter bootstrap za każdym razem wyświetla tę samą zawartość

263

Używam bootstrap z Twittera, określiłem 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>

I linki

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

Kiedy klikam którykolwiek z tych łączy po raz pierwszy, widzę poprawną treść, ale kiedy klikam inne linki, wyświetla tę samą treść załadowaną po raz pierwszy, nie aktualizuje treści.

Chcę, aby był aktualizowany za każdym razem, gdy zostanie kliknięty.

PS: Mogę z łatwością sprawić, by działało za pomocą niestandardowej funkcji jQuery, ale chcę wiedzieć, czy jest to możliwe dzięki natywnej modalnej funkcji zdalnego Bootstrap, ponieważ powinno to być dość łatwe i myślę, że tylko komplikuję.

Dhruv Kumar Jha
źródło
Ta sama poprawka, ale zmodyfikowana dla Bootstrap 3. Bootstrap 3 wprowadza przestrzenie nazw. plnkr.co/edit/HWSgSw?p=preview
Jeff H
5
Pamiętaj, że remotemoduły są przestarzałe od wersji Bootstrap v3.2.1 i znikną w wersji v4.
cvrebert

Odpowiedzi:

447

Problem jest dwojaki.

Po pierwsze , po utworzeniu instancji obiektu Modal jest on trwale dołączany do elementu określonego przez data-targeti kolejne wywołania, aby pokazać, że modal wywoła tylko toggle()ten obiekt, ale nie zaktualizuje wartości w options. Tak więc, chociaż hrefatrybuty są różne w różnych linkach, podczas przełączania modalu wartość parametru remotenie jest aktualizowana. W przypadku większości opcji można obejść ten problem, bezpośrednio edytując obiekt. Na przykład:

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

To jednak nie zadziała w tym przypadku, ponieważ ...

Po drugie , wtyczka Modal została zaprojektowana w taki sposób, aby ładować zdalny zasób do konstruktora obiektu Modal, co niestety oznacza, że ​​nawet jeśli zostanie dokonana zmiana w options.remote, nigdy nie zostanie przeładowana .

Prostym rozwiązaniem jest zniszczenie obiektu Modal przed kolejnymi przełączeniami. Jedną z opcji jest po prostu zniszczenie go po zakończeniu ukrywania:

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

Uwaga: Dostosuj selektory według potrzeb. To jest najbardziej ogólne.

Plunker

Lub możesz spróbować wymyślić bardziej skomplikowany schemat, aby zrobić coś takiego jak sprawdzenie, czy link uruchamiający modal różni się od poprzedniego. Jeśli tak, zniszcz; jeśli nie jest, to nie trzeba go ponownie ładować.

merv
źródło
1
@VladimirStarkov Przepraszam za to - wygląda na to, że zapomniałem hideklasy o modalu, więc jeśli twoje okno było zbyt małe, modal mógł blokować zdarzenia myszy na przyciskach. Z jakiegoś powodu JSFiddle.net jest dziś naprawdę zły (504 próbuje zaktualizować), więc po prostu zredagowałem przykład na plnkr.co, co i tak jest lepsze dla AJAX.
merv
3
jest jeszcze jeden problem: ciało .modal nadal będzie zawierało tekst, więc dodałem: <CODE> $ ('# myModal .modal-body'). tekst („Ładowanie ...”) </CODE> w detektorze ukrytych zdarzeń
rbp
5
bs.modalw $(this).removeData('bs.modal')pracował dla mnie z Bootstrap 3
jvannistelrooy
2
Pełny działający kod dla Boostrap 3 to$('body').on('hidden.bs.modal', '.modal', function () { $(this).removeData('bs.modal'); });
Christophe Fondacci
1
Sprawdziłbym również, czy ukryty modal jest ładowany ze zdalnego źródła, aby nie łamać modów o treści statycznej: var modalData = $(this).data('bs.modal'); if (modalData && modalData.options.remote)...
Wojtek Kruszewski
171

Do bootstrap 3 powinieneś użyć:

$('body').on('hidden.bs.modal', '.modal', function () {
    $(this).removeData('bs.modal');
});
Camilo Nova
źródło
17
Mój bohater. Uwielbiam te nieudokumentowane zmiany.
Jorin,
2
To bardzo pomogło. Bootstrap 3 nie jest kompatybilny z poprzednimi wersjami, a większość treści na SO (lub innych forach) dotyczy BS <3, więc wypróbowanie tych rozwiązań naprawdę marnuje dużo czasu.
Swapnil
7
Nie idealne: pokazuje krótko starą treść przed nową.
Laurent
3
Jeśli chcesz opróżnić modal, korzystając z powyższego przykładu, powinieneś być w stanie dodać następujące przed remoteDatawierszem lub po nim :$(this).empty()
jgillman,
11
Nie powinieneś używać $(this).empty(). remoteOpcja ładuje dane zdalnych do zagnieżdżonego <div class="modal-content">elementu. Użyj $('.modal-content', this).empty();zamiast tego.
Gavin
50

W przypadku Bootstrap 3.1 będziesz chciał usunąć dane i opróżnić modal-contentzamiast całego okna dialogowego (3.0), aby uniknąć migotania podczas oczekiwania na załadowanie zdalnej zawartości.

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

Jeśli używasz modów nie-zdalnych, powyższy kod oczywiście usunie ich zawartość po zamknięciu (źle). Może być konieczne dodanie czegoś do tych modów (np. .local-modalKlasy), aby nie miało to wpływu. Następnie zmodyfikuj powyższy kod, aby:

$(document).on("hidden.bs.modal", ".modal:not(.local-modal)", function (e) {
    $(e.target).removeData("bs.modal").find(".modal-content").empty();
});
slopapa
źródło
Na zdalnych stronach upewnij się, że nie ładujesz bibliotek bootstrap ani bibliotek jquery. Zabije każde odniesienie i pozostawi pustą modal pustą.
Bankzilla,
To nie działało dla mnie. Oto mój kod, który działa: $ (dokument) .on („hidden.bs.modal”, „.modal”, funkcja (e) {if (! $ (E.target) .is („. Local-modal „)) {$ (e.target) .removeData („ bs.modal ”). find („. modal-content ”). empty ();}});
Kevin
Kiedy używam $(e.target).removeData("bs.modal").find(".modal-content").empty();, mój modal jakoś się ukrywa i pojawia się tylko szara nakładka.
Axel
30

Dzięki merv. Zacząłem majstrować przy boostrap.js, ale twoja odpowiedź to szybkie i czyste obejście. Oto, co ostatecznie wykorzystałem w moim kodzie.

$('#modal-item').on('hidden', function() {
    $(this).removeData('modal');
});
Bienvenido David
źródło
21

Przyjęta odpowiedź nie działała dla mnie, więc wybrałem JavaScript.

<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
źródło
14

Działa to z FYI Bootstrap 3

$('#myModal').on('hidden.bs.modal', function () {
  $(this).removeData('bs.modal');
});
Dave Sag
źródło
7

Mój projekt jest wbudowany w Yii i używa wtyczki Bootstrap-Yii, więc ta odpowiedź jest ważna tylko wtedy, gdy używasz Yii.

Powyższa poprawka zadziałała, ale dopiero po pierwszym wyświetleniu modalu. Za pierwszym razem okazało się puste. Myślę, że dzieje się tak, ponieważ po mojej inicjacji kodu Yii wywołuje funkcję ukrywania modalu, usuwając w ten sposób moje zmienne inicjujące.

Odkryłem, że załatwienie wywołania removeData bezpośrednio przed kodem uruchamiającym modal załatwiło sprawę. Więc mój kod ma następującą strukturę ...

$ ("#myModal").removeData ('modal');
$ ('#myModal').modal ({remote : 'path_to_remote'});
Sean Toru
źródło
5

W Bootstrap 3.2.0 zdarzenie „on” musi znajdować się w dokumencie i należy opróżnić moduł:

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

W Bootstrap 3.1.0 zdarzenie „on” może znajdować się na ciele:

$('body').on('hidden.bs.modal', '.modal', function () {
    $(this).removeData('bs.modal');
});
Romain
źródło
Rozwiązanie 3.2 było jedyną rzeczą, która działała poprawnie dla mnie w Bootstrap 3.1 - używając podejścia body, niektóre z moich wydarzeń na modalu zostały odhaczone.
StuartQ
3

Dlaczego nie uczynić tego bardziej ogólnym z BS 3? Wystarczy użyć „[coś] modalnego” jako identyfikatora modalnego DIV.

$("div[id$='modal']").on('hidden.bs.modal',
    function () {
        $(this).removeData('bs.modal');
    }
);
użytkownik2763645
źródło
2

Jedyną działającą opcją dla mnie jest:

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

Używam Bootstrap 3 i mam wywoływaną funkcję, popup('popup content') która dołącza moduł modalny HTML.

Orkun Tuzel
źródło
2
to jedyna rzecz, która działała dla mnie w BS 3.3.6. również za pomocą szablonu kierownicy. Sugeruję jednak użycie dokumentu zamiast treści.
dbinott,
1

Dodanie $ (this) .html (''); aby wyczyścić widoczne dane, i działa całkiem dobrze

webstr
źródło
1

Jeśli podany jest zdalny adres URL, zawartość zostanie załadowana jeden raz za pośrednictwem jQuery metody ładowania i wstrzyknięta do div .modal-content. Jeśli korzystasz z interfejsu API danych, możesz alternatywnie użyć atrybutu href, aby określić źródło zdalne. Przykład tego pokazano poniżej

$.ajaxSetup ({
    // Disable caching of AJAX responses
    cache: false
});
Ciprian Mihalache
źródło
1

Dodałem coś takiego, ponieważ starsza treść jest wyświetlana, dopóki nie pojawi się nowa, z rozszerzeniem .html ('') wewnątrz zawartości .modal wyczyści HTML wewnątrz, mam nadzieję, że pomoże

$('#myModal').on('hidden.bs.modal', function () {
   $('#myModal').removeData('bs.modal');
   $('#myModal').find('.modal-content').html('');
});
Mau GM
źródło
To zdecydowanie najprostsza działająca odpowiedź, jaką znalazłem. Nic nie komplikuje odpowiedzi, kilka linii kodu i łatwość interpretacji. Działa idealnie za pierwszym razem, gdy się z tym nie zgadza.
Tarquin
0

Napisałem prosty fragment obsługujący odświeżanie modalu. Zasadniczo przechowuje kliknięty link w danych modalu i sprawdza, czy jest to ten sam link, który został kliknięty, usuwając lub nie modalne dane.

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
źródło
0

W przypadku Bootstrap 3 w modal.js zmieniłem:

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

do

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

(dodatkowe odstępy dodane dla przejrzystości)

Zapobiega to niechcianemu flashowaniu starej zawartości modalnej poprzez wywołanie empty () w kontenerze modalnym, a także usunięcie danych.

Stanton
źródło
0
        $('#myModal').on('hidden.bs.modal', function () {
            $(this).removeData('modal');
        });

Ten działa dla mnie.

Shawn Ang
źródło
0

To inne podejście działa dla mnie dobrze:

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

Który element HTML chcesz opróżnić (div, span cokolwiek).

Atul
źródło
0

Ten działa dla mnie:

modalny

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

scenariusz

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

links-area to obszar, w którym umieszczam dane i muszę je wyczyścić

dewaz
źródło
0

Rozszerzona wersja zaakceptowanej odpowiedzi przez @merv. Sprawdza również, czy ukryty modal jest ładowany ze zdalnego źródła i czyści starą zawartość, aby zapobiec flashowaniu.

$(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
źródło
-1

Testowane na wersji Bootstrap 3.3.2

  $('#myModal').on('hide.bs.modal', function() {
    $(this).removeData();
  });
Abudayah
źródło
1
To okropne rozwiązanie. Wywołanie .removeData()bez parametrów spowoduje, że jquery usunie wszystkie dane dołączone do tego elementu. Jeśli chodzi o problem PO, to wystarczyłby .removeData('bs.modal')lub .removeData('modal')byłby bardzo bezpieczny.
Julian Paolo Dayag,
-4

Powodzenia z tym:

$('#myModal').on('hidden.bs.modal', function () {
    location.reload();
});
Mappy
źródło
2
to jest bezużyteczne. ponowne załadowanie strony nie jest rozwiązaniem.
dbinott,