Twitter bootstrap remote modal affiche le même contenu à chaque fois


263

J'utilise Twitter bootstrap, j'ai spécifié 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>

Et les liens

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

Lorsque je clique sur l'un de ces liens pour la première fois, je vois le contenu correct, mais lorsque je clique sur d'autres liens, il affiche le même contenu chargé pour la première fois, il ne met pas à jour le contenu.

Je veux qu'il soit mis à jour à chaque fois que vous cliquez dessus.

PS: Je peux facilement le faire fonctionner via la fonction jQuery personnalisée, mais je veux savoir si c'est possible avec la fonction distante modale Bootstrap native, car cela devrait être assez facile et je suppose que je ne fais que compliquer les choses.


Même correctif, mais modifié pour Bootstrap 3. Bootstrap 3 introduit des espaces de noms. plnkr.co/edit/HWSgSw?p=preview
Jeff H

Réponses:


447

Le problème est double.

Tout d'abord , une fois qu'un objet Modal est instancié, il est attaché de manière persistante à l'élément spécifié par data-targetles appels suivants pour montrer que le modal ne fera appel toggle()qu'à lui, mais ne mettra pas à jour les valeurs dans le options. Ainsi, même si les hrefattributs sont différents sur vos différents liens, lorsque le modal est basculé, la valeur de remoten'est pas mise à jour. Pour la plupart des options, on peut contourner cela en modifiant directement l'objet. Par exemple:

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

Cependant, cela ne fonctionnera pas dans ce cas, car ...

Deuxièmement , le plugin Modal est conçu pour charger la ressource distante dans le constructeur de l'objet Modal, ce qui signifie malheureusement que même si une modification est apportée à la options.remote, elle ne sera jamais rechargée .

Un remède simple consiste à détruire l'objet Modal avant de basculer ultérieurement. Une option consiste à simplement le détruire une fois qu'il se cache:

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

Remarque: ajustez les sélecteurs selon vos besoins. C'est le plus général.

Plunker

Ou vous pouvez essayer de trouver un schéma plus compliqué pour faire quelque chose comme vérifier si le lien qui lance le modal est différent du précédent. Si c'est le cas, détruisez; sinon, pas besoin de recharger.


1
@VladimirStarkov Désolé - il semble que j'aie oublié la hideclasse sur le modal, donc si votre fenêtre était trop petite, le modal peut avoir bloqué les événements de la souris sur les boutons. Pour une raison quelconque, JSFiddle.net est vraiment mauvais ce matin (un 504 a essayé de se mettre à jour), donc je viens de refaire l'exemple sur plnkr.co, ce qui est mieux pour AJAX de toute façon.
merv

3
il y a un autre problème: le .modal-body contiendra toujours le texte, alors j'ai ajouté: <CODE> $ ('# myModal .modal-body'). text ("Loading ...") </CODE> dans l'auditeur d'événements cachés
rbp

5
bs.modalen a $(this).removeData('bs.modal')travaillé pour moi avec Bootstrap 3
jvannistelrooy

2
Le code de travail complet pour Boostrap 3 est$('body').on('hidden.bs.modal', '.modal', function () { $(this).removeData('bs.modal'); });
Christophe Fondacci

1
Je vérifierais également si le modal caché est chargé à partir d'une source distante, afin de ne pas casser les modaux avec du contenu statique: var modalData = $(this).data('bs.modal'); if (modalData && modalData.options.remote)...
Wojtek Kruszewski

171

Pour bootstrap 3, vous devez utiliser:

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

17
Mon héros. J'adore ces changements non documentés.
Jorin

2
Cela a beaucoup aidé. Bootstrap 3 n'est pas rétrocompatible et la plupart du contenu sur SO (ou d'autres forums) concerne BS <3, essayer ces solutions fait perdre beaucoup de temps.
Swapnil

7
Pas parfait: il montre brièvement l'ancien contenu avant le nouveau contenu.
Laurent

3
Si vous voulez vider le modal en utilisant l'exemple ci-dessus, vous devriez pouvoir ajouter ce qui suit avant ou après la remoteDataligne:$(this).empty()
jgillman

11
Vous ne devriez pas utiliser $(this).empty(). L' remoteoption charge les données distantes dans l' <div class="modal-content">élément imbriqué . Utilisez $('.modal-content', this).empty();plutôt.
Gavin

50

Pour Bootstrap 3.1, vous souhaiterez supprimer des données et vider la modal-contentplutôt que la boîte de dialogue entière (3.0) pour éviter le scintillement en attendant le chargement du contenu distant.

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

Si vous utilisez des modaux non distants, le code ci-dessus supprimera bien sûr leur contenu une fois fermé (mauvais). Vous devrez peut-être ajouter quelque chose à ces modaux (comme une .local-modalclasse) afin qu'ils ne soient pas affectés. Modifiez ensuite le code ci-dessus pour:

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

Sur les pages distantes, assurez-vous que vous ne chargez pas les bibliothèques d'amorçage ou jquery. Il tuera toute référence et vous laissera avec un modal vide.
Bankzilla

Cela ne fonctionnait pas pour moi. Voici mon code qui fonctionne: $ (document) .on ("hidden.bs.modal", ".modal", function (e) {if (! $ (E.target) .is (". Local-modal) ")) {$ (e.target) .removeData (" bs.modal "). find (". modal-content "). empty ();}});
Kevin

Lorsque j'utilise, $(e.target).removeData("bs.modal").find(".modal-content").empty();c'est comme si mon modal était en quelque sorte caché et seule la superposition grise apparaît.
Axel

30

Merci merv. J'ai commencé à bricoler boostrap.js mais votre réponse est une solution de contournement rapide et propre. Voici ce que j'ai fini par utiliser dans mon code.

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

21

La réponse acceptée n'a pas fonctionné pour moi, alors je suis allé avec JavaScript pour le faire.

<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

Cela fonctionne avec Bootstrap 3 FYI

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

7

Mon projet est construit en Yii et utilise le plugin Bootstrap-Yii, donc cette réponse n'est pertinente que si vous utilisez Yii.

Le correctif ci-dessus a fonctionné mais seulement après la première fois que le modal a été affiché. La première fois, il est venu vide. Je pense que c'est parce qu'après mon initiation du code, Yii appelle la fonction de masquage du modal, effaçant ainsi mes variables d'initiation.

J'ai trouvé que placer l'appel removeData juste avant le code qui a lancé le modal a fait l'affaire. Donc mon code est structuré comme ça ...

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

5

Dans Bootstrap 3.2.0, l'événement "on" doit être sur le document et vous devez vider le modal:

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

Dans Bootstrap 3.1.0, l'événement "on" peut être sur le corps:

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

La solution 3.2 était la seule chose qui fonctionnait correctement pour moi dans Bootstrap 3.1 - en utilisant l'approche du corps, certains de mes événements sur modal sont devenus décrochés.
StuartQ

3

Pourquoi ne pas le rendre plus général avec BS 3? Utilisez simplement "[quelque chose] modal" comme ID du DIV modal.

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

2

La seule option de travail pour moi est:

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

J'utilise Bootstrap 3 et j'ai une fonction appelée popup('popup content') qui ajoute la boîte modale html.


2
c'est la seule chose qui a fonctionné pour moi avec BS 3.3.6. en utilisant également le modèle de guidon. Je suggère cependant d'utiliser le document au lieu du corps.
dbinott

1

Ajout d'un $ (this) .html (''); pour effacer également les données visibles, et cela fonctionne très bien


1

Si une URL distante est fournie, le contenu sera chargé une fois via la méthode de chargement de jQuery et injecté dans la div .modal-content. Si vous utilisez l'api de données, vous pouvez également utiliser l'attribut href pour spécifier la source distante. Un exemple de ceci est illustré ci-dessous

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

1

J'ai ajouté quelque chose comme ça, car l'ancien contenu est affiché jusqu'à ce que le nouveau apparaisse, avec .html ('') à l'intérieur du contenu .modal effacera le HTML à l'intérieur, j'espère que cela aide

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

C'est de loin la réponse de travail la plus simple que j'ai trouvée. Rien de compliqué dans la réponse, peu de lignes de code et facile à interpréter. A parfaitement fonctionné la première fois sans jouer avec.
Tarquin

0

J'ai écrit un simple extrait traitant de l'actualisation du modal. Fondamentalement, il stocke le lien cliqué dans les données du modal et vérifie s'il s'agit du même lien cliqué, supprimant ou non les données 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');
    });
};

0

Pour Bootstrap 3, dans modal.js j'ai changé:

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

à

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

(espacement supplémentaire ajouté pour plus de clarté)

Cela empêche tout flash indésirable de l'ancien contenu modal en appelant empty () sur le conteneur modal ainsi qu'en supprimant les données.


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

Celui-ci fonctionne pour moi.


0

Cette autre approche fonctionne bien pour moi:

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

Quel élément html que vous souhaitez vider (div, span, etc.).


0

Celui-ci fonctionne pour moi:

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>

scénario

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

liens-zone est la zone où je mets les données et besoin d'effacer


0

Version étendue de la réponse acceptée par @merv. Il vérifie également si le modal caché est chargé à partir d'une source distante et efface l'ancien contenu pour l'empêcher de clignoter.

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

Testé sur Bootstrap version 3.3.2

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

1
C'est une terrible solution. L'appel .removeData()sans paramètres indiquera à jquery de supprimer toutes les données attachées à cet élément. En ce qui concerne le problème du PO, .removeData('bs.modal')ou .removeData('modal')pourrait suffire et est très sûr.
Julian Paolo Dayag

-4

Bonne chance avec celui-ci:

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

2
c'est inutile. recharger la page n'est pas la solution.
dbinott
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.