web-dev-qa-db-fra.com

Comment obtenir une longueur de tableau observable?

J'essaie de créer un tableau d'éléments de ligne de contrat (CLIN) qui seront affichés en tant qu'éléments div individuels sous un en-tête d'informations générales sur le contrat.

Je suis capable de faire fonctionner les observables normaux, mais il semble que le passage du tableau via le constructeur du modèle de vue ne crée aucune partie du tableau observable des clins.

J'ai un jsFiddle qui illustre mon problème . Ce qui est étrange pour moi, c'est que la data-bind="text: clins.length() sur la balise span HTML ne retourne même pas zéro, mais ne rend rien à la place.

Est-il possible d'activer le débogage dans un jsFiddle ou dois-je voir un avertissement/erreur?

45
Karl Anderson

Les erreurs des pages jsfiddle sont envoyées à votre navigateur.

Quant à votre erreur, essayez ceci:

<span data-bind="text: clins().length">

Cela transforme le observableArray en array et utilise la propriété length du tableau.

Voir mise à jour de jsfiddle également .

79
kendaleiv

TL; DR/Quick Fix

Exécutez le observableArray en tant que fonction pour obtenir le tableau sous-jacent, alors obtenez sa longueur:

<!--                                                     ↓↓                              -->
myObsArray's length is: <span data-bind="text: myObsArray().length"></span>

Pourquoi cela se produit-il?

Permettez-moi de fournir une réponse qui fournit quelques détails en plus de la solution de @ kendaleiv , et qui répond également à une question très connexe, je pense que beaucoup de gens ont:

PourquoimyObsArray.length toujours retourne 0 (zéro)?

Une repro typique d'un tel scénario serait la suivante:

ko.applyBindings({ myObsArray: ko.observableArray(["one", "two", "three"]) });
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
myObsArray.length = <span data-bind="text: myObsArray.length"></span>

L'extrait de code indique "longueur = 0", au lieu de "longueur = 3".

L'élément clé à noter ici: ko.observableArray Est une fonction ... qui renvoie une fonction .

C'est vrai: si vous en affectez le résultat à une variable ou un membre, comme myObsArray dans l'exemple, cette variable sera une référence à une fonction. Donc, si vous demandez

myObsArray.length

alors vous demandez en fait la propriété Function.length : le nombre d'arguments que prend la fonction. Pour une fonction renvoyée par ko.observableArray, Ce sera 0 (zéro).

Comment réglons-nous cela?

La correction donnée dans d'autres réponses est correcte, permettez-moi de réitérer ici avec l'exemple de cette réponse. Pour obtenir la longueur du "tableau observé", vous devez invoquer ladite fonction pour obtenir le tableau, et alors obtenir sa longueur:

ko.applyBindings({ myObsArray: ko.observableArray(["one", "two", "three"]) });
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
myObsArray.length = <span data-bind="text: myObsArray().length"></span>

Enfin, comme note de bas de page, le code OP est quelque chose d'équivalent à:

myObsArray.length()

Cela trouvera la propriété Function.length susmentionnée et tentera de l'exécuter en tant que fonction (ce qui n'est pas le cas), et ne renverra pas 0 mais se bloquera à la place. Attention à ne pas invoquer length en tant que fonction, mais le observable. Appelez toujours length en tant que variable membre.

Est-ce que/peut/pourrait-il être changé?

Très tôt, les développeurs de KO ont envisagé ce problème; dès Github n ° 4 . Ce problème explique également ce que j'ai essayé de couvrir ci-dessus et montre également qu'en fin de compte, il n'y avait pas grand-chose à faire pour le changer.

18
Jeroen

Pour tous ceux qui souhaitent obtenir la longueur d'un tableau observable sans le _destroyed items, vous pouvez utiliser cette fonction:

ko.observableArray.fn.totalVisible = function() {
    var items = this(), count = 0;

    if (items == null || typeof items.length === "undefined") {
        return 0;
    }

    for (var i = 0, l = items.length; i < l; i++) {
        if (items[i]._destroy !== true) {
            count++;
        }
    }

    return count;
};

Ensuite pour l'utiliser:

myObservableArray.totalVisible();
5
David Sherret