web-dev-qa-db-fra.com

L'événement JQuery ne se déclenchera pas après un appel ajax

C'est un problème assez étrange avec jQuery. Je charge un div

<div id="container">

sur le chargement de la page. Chaque enregistrement est une donnée tabulaire à laquelle est associée une fonction ajax de "suppression". Lorsque la page se charge et que vous cliquez sur le lien "Supprimer", l'appel ajax se déclenche correctement. Cependant, une fois que l'événement est déclenché, les données sont renvoyées par l'appel ajax et la div est renseignée (mais la page n'est ni rafraîchie ni rechargée). Lorsque je clique à nouveau sur le lien, le script ajax ne se déclenche pas. Voici mon code:

$(document).ready(function() {
    $("button.done").button({
    }).click(function() {
        var BatchID = $("input#BatchID").val();
        var Amount = $("input#Amount").val();
        var Name = $("input#CheckName").val();
        var Check_Number = $("input#Check_Number").val();
        var Company = $("select#Company").val();
        var Department = $("select#Department").val();
        $.ajax({
            type: 'GET',
            url: '/app/usagCheckEntryWS.html',
            data: {
                "BatchID" : BatchID,
                "Amount" : Amount,
                "Name" : Name,
                "Check_Number" : Check_Number,
                "Company" : Company,
                "Department" : Department
            },
            success: function (data) {
                    var ang = '';
                    var obj = $.parseJSON(data);
                    $.each(obj, function() {
                       ang += '<table><tr><td width="45">' + this["RefID"] + '</td><td width="140">' + this["Name"] + '</td><td width="95">' + this["CheckNumber"] + '</td><td align="right" width="70">$' + this["Amount"] + '</td><td width="220" style="padding-left: 15px;">' + this["Description"] + '</td><td><div class="delete" rel="' + this["RefID"] + '"><span>Delete</span></div></td></tr></table>';
                    });
                    $('#container').html(ang);
                    $("input#Amount").val('');
                    $("input#CheckName").val('');
                    $("input#Check_Number").val('');
                    $("select#Company").val('MMS');
                    $("th#dept").hide();
                    $('input#CheckName').focus();
            }
        });
    });
});
58
Matthew Colley

Lorsque vous supprimez un élément, puis le remplacez (via javascript), il perd toutes les liaisons d'événement qui lui ont été ajoutées lors du chargement de la page.

(Ceci s'applique également au contenu ajouté à la page après le chargement de la page - c'est-à-dire le contenu chargé en ajax)

Il existe plusieurs solutions possibles pour cela.

1) Encapsulez votre code "contraignant" et appelez-le à la fois au chargement de la page et immédiatement après que l'élément en question soit rajouté à la page. Par exemple:

$(document).ready(function(){
    // bind event handlers when the page loads.
    bindButtonClick();
});

function bindButtonClick(){
    $('.myClickableElement').click(function(){
        ... event handler code ...
    });
}

function updateContent(){
    $.ajax({
        url : '/ajax-endpoint.php',
        data : {'onMyWay' : 'toServer'},
        dataType : 'html',
        type : 'post',
        success : function(responseHtml){
            // .myClickableElement is replaced with new (unbound) html element(s)
            $('#container').html(responseHtml);

            // re-bind event handlers to '.myClickableElement'
            bindButtonClick();  
        }
    });
}

2) La manière la plus élégante de gérer cela : utilisez méthode .on () de jQuery . Vous pouvez ainsi lier les gestionnaires d’événements à des éléments autres que la cible de l’événement, c’est-à-dire un élément qui ne sera jamais supprimé de la page.

$(document).ready(function(){
    $('body').on('click','.myClickableElement',function(){
        ... event handler code ....
    });
});

Quelques explications supplémentaires:

La méthode .on() utilise délégation d'événement pour dire à un parent élément pour conserver le code de votre gestionnaire d’événements (3ème argument) et le déclencher lorsque la cible de l’événement (2ème argument) comporte un certain type d’événement (1er argument).

Si vous utilisez une version de jQuery antérieure à 1.7, utilisez la méthode delegate maintenant obsolète qui fait essentiellement la même chose.

En outre, il convient de noter qu'en raison de la façon dont les événements "remontent" dans l'arborescence des doms, la cible de l'événement (second argument de la méthode .on ()) doit être un descendant de l'élément délégué (sélecteur de l'objet jQuery). Par exemple, , ce qui suit NE fonctionnerait PAS

<div id="container-1">
    <div>
        <div id="another-div">
            Some Stuff
        </div>
    </div>
</div>

<div id="container-2">
    <a id="click-me">Event Target!!!</a>
</div>

<script type="text/javascript">
    $('#container-1').on('click','#click-me',function(){
        ... event handler code ....
    });
</script>

Les éléments body ou document sont généralement des choix sûrs, car chaque élément de la page est généralement un descendant.

160
Jason Fingar

Vous pouvez inclure le script d'événement dans DIV et exécuter une commande Replaceall après le chargement dynamique du contenu.

<div class="somescript">
-- Event Script that you want to map with dnamically added content
<div>

- Chargez dynamiquement votre contenu et exécutez la commande ci-dessous après celle-ci.

$(".somescript").replaceAll($(".somescript"));

Une fois que le contenu chargé dynamiquement est chargé et que la commande replace a été exécutée, les événements sont mappés et le code s'exécute correctement.

1
Srikanth Srikanth

Mon commentaire est trop long, désolé.

Juste une question et un commentaire, même si je vois que c'est un vieux post. J'ai eu beaucoup de difficulté à utiliser: $ (document) .on ('clic', '#xxx ", fonction (e) {}); pour attacher des gestionnaires au contenu renvoyé avec AJAX, par opposition à une fonction () { $ ('# xxx) .on (' cliquez ', fonction (e) {});} et appelez-le après l'appel AJAX revient avec succès. Existe-t-il une astuce ou un guide?) La délégation est impliquée et j’ai essayé de l’utiliser mais cela ne fonctionne pas souvent. Je pourrais essayer de déléguer à l’élément englobant. Peut-être que cela n’éclate pas dans le document ou le corps pour une raison quelconque?

0
SScotti