web-dev-qa-db-fra.com

Impossible d'appeler Object.keys dans angularjs

J'utilise un accordéon UI.Bootstrap et j'ai défini mon cap comme suit:

<accordion-group ng=repeat="(cname, stations) in byClient">
    <accordion-heading>
        {{ cname }} <span class="pull-right"> {{ Object.keys(stations).length }} Stations</span>
    </accordion-heading>

Lorsque cela affiche la Object.keys(stations).length ne résout rien. Si je mets la même longueur d'appel dans mon contrôleur, je récupère le nombre attendu. Quelque chose empêche-t-il l'appel de méthode de fonctionner dans AngularJS?

Le reste de l'accordéon qui utilise stations agit comme prévu, donc je sais qu'il est rempli correctement. La structure de données byClient ressemble en gros à ceci:

{
    "Client Name" : {
        "Station Name": [
            {...},
            {...}
        ]
    }
 }
40
Gargoyle

Oui, c'est parce que Object fait partie de window/global et que angular ne peut pas évaluer cette expression par rapport à la portée. Lorsque vous spécifiez Object.keys dans votre liaison angulaire, essayez de l'évaluer par rapport à $scope et ne le trouve pas. Vous pouvez stocker la référence de object.keys dans un utilitaire de rootScope et l'utiliser n'importe où dans l'application.

Quelque chose comme ça:-

angular.module('yourApp',[deps...]).run(function($rootScope){
  //Just add a reference to some utility methods in rootscope.
  $rootScope.Utils = {
     keys : Object.keys
  }

  //If you want utility method to be accessed in the isolated Scope 
  //then you would add the method directly to the prototype of rootScope 
  //constructor as shown below in a rough implementation.

  //$rootScope.constructor.prototype.getKeys = Object.keys;

});

et l'utiliser comme: -

<span class="pull-right"> {{ Utils.keys(stations).length }} Stations</span>

Eh bien, ce sera disponible pour tous les scopes enfant sauf les scopes isolés. Si vous envisagez de le faire sur la portée isolée (par exemple: - Directives de portée isolées), vous devrez ajouter la référence Object.keys sur la portée ou exposer une méthode sur la portée qui renverra la longueur.

Ou mieux encore, créez un filtre de format pour renvoyer la longueur de clé et l'utiliser partout.

app.filter('keylength', function(){
  return function(input){
    if(!angular.isObject(input)){
      throw Error("Usage of non-objects with keylength filter!!")
    }
    return Object.keys(input).length;
  }
});

et fait:-

{{ stations | keylength }}

Démo

77
PSL

Utilisez la fonction pour déterminer le nombre de propriétés d'objet:

$scope.keyLength = function (obj) {
    return Object.keys(obj).length;
}

et utilise:

{{ keyLength(myObj) }}
3
Alex V

Je pense que les filtres sont le moyen le plus angulaire de manipuler des structures dans un code de template

angular.module('app.filters').filter('objectKeysLength', [function() {
    return function(items) {
        return Object.keys(items).length;
    };
}]);

angular.module('app.filters').filter('objectKeys', [function() {
    return function(item) {
        if (!item) return null;
        var keys = Object.keys(item);
        keys.sort();
        return keys;
    };
}]);
2
jjmontes

Si quelqu'un cherche une solution angulaire 2 ou supérieure. Il a maintenant hat keyvalue pipe, qui peut être utilisé pour interagir sur des objets

0