web-dev-qa-db-fra.com

Est-ce que AJAX contenu chargé obtenir un "document.ready"?

Hier, j’ai eu un problème où un gestionnaire d’événements .on('click') que j’assignais ne fonctionnait pas correctement. Il s’est avéré que c’est parce que j’essayais d’appliquer cette .on('click') avant que cet élément n’existe dans le DOM, car il était chargé via AJAX et n’existait donc pas encore lorsque la document.ready() est arrivée à ce point.

Je l'ai résolu avec une solution de contournement maladroite, mais ma question est la suivante: si je mettais une balise <script> dans le contenu ajax chargé et dans un autre document.ready(), la seconde document.ready() serait-elle analysée SEULEMENT une fois le contenu ajax chargé? En d'autres termes, considère-t-il que le contenu ajax chargé séparément est un autre document, et si oui, le fait d'avoir un autre document.ready() dans ce code HTML chargé avec ajax fonctionne-t-il comme je le pense?

Alternativement Quel serait un meilleur moyen de gérer cette situation? (nécessité d'attacher un écouteur d'événement à un élément DOM qui n'existe pas encore sur document.ready())

36
user2762294

Pour répondre à votre question: Non, document.ready ne sera pas réactivé une fois la demande ajax complétée. (Le contenu de l'ajax est chargé dans votre document, il n'y a donc pas de second document pour le contenu de l'ajax).

Pour résoudre votre problème, ajoutez simplement l'écouteur d'événement à l'élément où vous y insérez le contenu ajax . Par exemple:

$( "div.ajaxcontent-container" ).on( "click", "#id-of-the-element-in-the-ajax-content", function() {
  console.log($( this ));
});

Pour #id-of-the-element-in-the-ajax-content, vous pouvez utiliser n’importe quel sélecteur que vous utiliseriez dans $("selector"). La seule différence est que seuls les éléments sous div.ajaxcontent-container seront sélectionnés.

Fonctionnement: Tant que div.ajaxcontent-container existe, tous les éléments (s’ils existent maintenant ou dans le futur) qui correspondent au sélecteur #id-of-the-element-in-the-ajax-content déclenchent cet événement.

32
nbar

Javascript dans l'appel ajax résultant ne sera pas exécuté (par défaut) pour des raisons de sécurité. En outre, vous ne pouvez pas lier directement un événement à des éléments non existants.
Vous pouvez lier un événement à un parent qui existe, et lui dire de vérifier ses enfants: 

$(document).ready(function(){
    $(document).on('eventName', '#nonExistingElement', function(){ alert(1); }
    // or:
    $('#existingParent').on('eventName', '#nonExistingElement', function(){ alert(1); }
});

Essayez toujours de vous rapprocher le plus possible de l'élément déclencheur, cela évitera les bulles inutiles dans le DOM.


Si vous avez des fonctions étranges, vous pouvez faire quelque chose comme ceci:

function bindAllDocReadyThings(){
    $('#nonExistingElement').off().on('eventName', function(){ alert(1); }
    // Note the .off() this time, it removes all other events to set them again
}
$(document).ready(function(){
    bindAllDocReadyThings();
});
$.ajaxComplete(function(){
    bindAllDocReadyThings();
});
10
Martijn

essayez ceci, cela ne fonctionne pas car votre contrôle n'est pas encore créé et que vous essayez de joindre un événement. Si vous utilisez événement, il fonctionnera correctement. laissez-moi savoir si vous rencontrez des problèmes.

$(document).ready(function(){
    $(document).on('click', '#element', function (evt) {
        alert($(this).val());
    });
});
5

La réponse ici est un événement délégué:

JSFiddle

JSFiddle - Vraiment dynamique

jQuery

$(document).ready(function(){
    // Listen for a button within .container to get clicked because .container is not dynamic
    $('.container').on('click', 'input[type="button"]', function(){
        alert($(this).val());
    });

    // we bound the click listener to .container child elements so any buttons inside of it get noticed
    $('.container').append('<input type="button" class="dynamically_added" value="button2">');
    $('.container').append('<input type="button" class="dynamically_added" value="button3">');
    $('.container').append('<input type="button" class="dynamically_added" value="button4">');
    $('.container').append('<input type="button" class="dynamically_added" value="button5">');
});

HTML

<div class="container">
    <input type="button" class="dynamically_added" value="button1">
</div>
2
MonkeyZeus

Je travaille sur une base de code avec un ami qui a une exigence similaire. L'option de gestionnaire d'événements délégué est définitivement préférable si vous souhaitez uniquement attacher des gestionnaires d'événements. Une alternative, en particulier si vous devez effectuer un autre traitement DOM dans votre fonction $(document).ready, consiste à insérer le code que vous souhaitez exécuter dans un élément de script à la fin de votre code. Fondamentalement, au lieu de:

<script type="text/javascript">
  $(document).ready(function() {
    // Your code here
  });
</script>
<!-- rest of dynamically loaded HTML -->

Essayez d’échanger le script et le reste du code HTML afin d’obtenir:

<!-- rest of dynamically loaded HTML -->
<script type="text/javascript">
  // Your code here
</script>

Cela oblige le navigateur à traiter votre code uniquement une fois qu'il a chargé tous les autres éléments DOM du code HTML chargé dynamiquement. Bien sûr, cela signifie que vous devez vous assurer que le HTML inséré n'a pas de conséquences inattendues sur l'interface utilisateur en utilisant CSS/HTML au lieu de JS. C'est un vieux truc en Javascript des années passées. En prime, vous n'avez plus besoin de jQuery pour cela.

Je devrais mentionner que dans Chromium v34, placer un deuxième appel $(document).ready à l'intérieur d'une balise <script> dans le code HTML chargé de manière dynamique semble attendre que le DOM chargé de manière dynamique se charge, puis exécute la fonction comme vous l'avez décrit. Je ne suis pas sûr que ce comportement soit standard, car il m’a causé beaucoup de problèmes en essayant d’automatiser les tests contenant ce type de code.

0
jeteon

JQuery AJAX .load () a une fonctionnalité intégrée pour gérer ceci . Au lieu de simplement $('div#content').load('such_a_such.url');, vous devez inclure une fonction de rappel. JQuery .load () offre de la place pour les éléments suivants:

$('div#content').load('such_a_such.url',
    { data1: "First Data Parameter",
      data2: 2,
      data3: "etc" },
    function(){ $('#span1').text("This function is the equivalent of");
                $('#span2').text("the $(document).ready function.");
    }
 );

Cependant, vous n'avez pas besoin d'inclure l'argument de données.

$ ("#result") .load ("ajax/test.html", function () { alert ("Le chargement a été effectué."); });

http://api.jquery.com/load/

0