web-dev-qa-db-fra.com

Pourquoi mon sélecteur JQuery renvoie-t-il un n.fn.init [0] et de quoi s'agit-il?

J'ai un ensemble de cases à cocher générées dynamiquement, chacune d'elles ayant un attribut data-id correspondant à un identifiant d'entier de base de données. Lorsque je remplis mon formulaire html avec un objet à modifier, il existe une liste d'entiers représentant les cases à cocher qui doivent être cochées. Les cases à cocher sont entourées d'une div avec la classe checkbox-wrapper.

Donc, html ressemble à ceci:

<div class="checkbox-wrapper">
    <input type="checkbox" id="checkbox1" data-id="1">
    <label for="checkbox1">Checkbox 1</label>
</div>
<div class="checkbox-wrapper">
    <input type="checkbox" id="checkbox2" data-id="2">
    <label for="checkbox2">Checkbox 2</label>
</div>
<div class="checkbox-wrapper">
    <input type="checkbox" id="checkbox3" data-id="99">
    <label for="checkbox3">Checkbox 99</label>
</div>

Notez que l'id est exécuté sur des numéros d'index d'incrémentation automatique, alors que data-id peut avoir une valeur différente Je veux les sélectionner par data-id.

Maintenant, en utilisant JQuery, je sais que je peux sélectionner les cases à cocher appropriées comme ceci:

$(".checkbox-wrapper>input[data-id='99']");
$(".checkbox-wrapper>input[data-id='1']");

Cela fonctionne dans ma console, en chrome, et renvoie l'élément DOM correspondant. De même, ci-dessous, coche les cases à cocher:

$(".checkbox-wrapper>input[data-id='99']").prop("checked", "checked");
$(".checkbox-wrapper>input[data-id='1']").prop("checked", "checked");

Cependant, si je parcours une liste d'entiers dans mon code javascript (pas directement dans la console) et que je consigne les éléments renvoyés, en fonction des valeurs id, j'obtiens des résultats étranges:

var ids = [1,2]
$.each(ids, function(index, myID){
    console.log($(".checkbox-wrapper>input[data-id='"+myID+"']"));
    $(".checkbox-wrapper>input[data-id='"+myID+"']").prop("checked", "checked");    
}); 

Tout d’abord, aucune case à cocher n’est cochée. Deuxièmement, ma console affiche des résultats étranges:

n.fn.init[0]
    context: document
    length: 0
    prevObject: n.fn.init[1]
    selector: ".checkbox-wrapper>input[data-id='1']"
    __proto__: n[0]

n.fn.init[0]
    context: document
    length: 0
    prevObject: n.fn.init[1]
    selector: ".checkbox-wrapper>input[data-id='2']"
    __proto__: n[0]

Le sélecteur imprimé Strings semble parfait. Les mêmes sélecteurs renvoient les éléments DOM, lorsqu'ils sont écrits directement dans la console Chrome. Ensuite, ils renvoient des objets comme celui-ci:

[<input type=​"checkbox" id=​"checkbox1" data-id=​"1">​]

Qu'est-ce que n.fn.init [0] et pourquoi est-il renvoyé? Pourquoi mes deux fonctions JQuery apparemment identiques donnent-elles des résultats différents?

32
KjetilNordin

Une autre approche (à l'intérieur de $function pour s'assurer que la each est exécutée sur document ready):

var ids = [1,2];
$(function(){
  $('.checkbox-wrapper>input[type="checkbox"]').each(function(i,item){
    if(ids.indexOf($(item).data('id')) > -1){
       $(item).prop("checked", "checked");
    }
  });
});

Violon de travail: https://jsfiddle.net/robertrozas/w5uda72v/

Qu'est-ce que n.fn.init [0] et pourquoi est-il renvoyé? Pourquoi mes deux fonctions JQuery apparemment identiques donnent-elles des résultats différents?

Réponse: Il semble que vos éléments ne soient pas encore dans le DOM, lorsque vous essayez de les trouver. Comme @Rory McCrossan l'a souligné, le length:0 signifie qu'il ne trouve aucun élément en fonction de vos critères de recherche.

À propos de n.fn.init[0], regardons le cœur de la bibliothèque Jquery:

var jQuery = function( selector, context ) {
   return new jQuery.fn.init( selector, context );
};

Looks familiar, right?, now in a minified version of jquery, this should looks like:

var n = function( selector, context ) {
   return new n.fn.init( selector, context );
};

Ainsi, lorsque vous utilisez un sélecteur, vous créez une instance de la fonction jQuery; lorsqu'il trouve un élément basé sur les critères de sélection, il renvoie les éléments correspondants; lorsque le critère ne correspond à rien, il renvoie l'objet prototype de la fonction.

22
Hackerman

Voici comment faire une vérification rapide pour voir si n.fn.init[0] est causé par le non chargement de vos éléments DOM dans le temps. Retardez votre fonction de sélecteur en l'enveloppant dans la fonction setTimeout comme ceci:

function timeout(){ 

    ...your selector function that returns n.fn.init[0] goes here...

}

setTimeout(timeout, 5000)

Votre fonction de sélection s’exécutera avec un délai de 5 secondes, ce qui devrait suffire à charger presque tout.

Ceci est juste un hack grossier pour vérifier si DOM est prêt ou non pour votre fonction de sélecteur. Ce n'est pas une solution (permanente). 

Les méthodes préférées pour vérifier si le DOM est chargé avant d'exécuter votre fonction sont les suivantes:

1) Enveloppez votre fonction de sélection dans

$(document).ready(function(){  ... your selector function...  };

2) Si cela ne fonctionne pas, utilisez DOMContentLoaded

3) Try window.onload , qui attend que toutes les images soient chargées en premier, c'est pourquoi il est préférable

window.onload = function () {  ... your selector function...  }

4) Si vous attendez le chargement d'une bibliothèque chargée en plusieurs étapes ou son propre retard, vous aurez peut-être besoin d'une solution personnalisée complexe. C'est ce qui m'est arrivé avec la bibliothèque "MathJax". Cette question explique comment vérifier si la bibliothèque MathJax a chargé ses éléments DOM, si elle est utile.

5) Enfin, vous pouvez vous en tenir à la fonction setTimeout codée en dur, ce qui la laisse peut-être 1-3 secondes. Ceci est en fait la méthode la moins préférée à mon avis.

Cette liste de corrections est probablement loin d'être parfaite, alors tout le monde est invité à la modifier.

5
Arthur Tarasov

J'ai rencontré ce problème parce que mon sélecteur dépendait de id pendant ce temps I did not set id for my element

ma selector était 

$("#EmployeeName")

mais mon HTML element

<input type="text" name="EmployeeName">

alors assurez-vous que vos critères de sélection sont valables

4
Basheer AL-MOMANI

Votre objet de résultat est un élément jQuery, pas un tableau javascript. Le tableau que vous souhaitez doit être sous .get ()

Comme la valeur de retour est un objet jQuery, qui contient un tableau, c’est très commun d'appeler .get () sur le résultat pour travailler avec un tableau de base . http://api.jquery.com/map/

2
celerno

Je veux juste ajouter quelque chose à ces bonnes réponses. Si votre élément DOM ne se charge pas à temps. Vous pouvez toujours définir la valeur.

let Ctrl = $('#mySelectElement'); ... Ctrl.attr('value', myValue);

après cela, les élémentsmostDOM qui acceptent un attribut value doivent être renseignés correctement.

0