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


Ta sama poprawka, ale zmodyfikowana dla Bootstrap 3. Bootstrap 3 wprowadza przestrzenie nazw. plnkr.co/edit/HWSgSw?p=preview
Jeff H

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


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

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

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

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")})
    })
})

14

Działa to z FYI Bootstrap 3

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

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

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

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

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.


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


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
});

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

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

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.


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

Ten działa dla mnie.


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

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


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ć


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


-1

Testowane na wersji Bootstrap 3.3.2

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

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

2
to jest bezużyteczne. ponowne załadowanie strony nie jest rozwiązaniem.
dbinott,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.