Sous-objet de ressource $ angulaire avec des méthodes personnalisées

Dans la plupart des cas, le résultat de la méthode <custom-resource>.query() est un tableau, qui peut être facilement étendu avec certaines méthodes (logiques métier) avec le code suivant (usine):

 var Data = $resource('http://..'); Data.prototype.foo = function() {return ...}; 

C'est parfait pour l'utilisation avec ng-repeat / ng-class, de la manière suivante:

 <tr ng-repeat="item in responseData" ng-class="{warning: item.foo()}">..</tr> 

Mon problème est que chaque réponse de la liste est encapsulée dans un objet qui, en plus de la liste actuelle, a des méta-propriétés (informations de tri, etc.), donc l'objet final renvoyé est comme ceci:

 { order_field: "name", items: [{..}, {..},{..}] } 

Maintenant, comment puis-je faire la même chose que précédemment avec ng-repeat / ng-class?

 <tr ng-repeat="item in responseData.items" ng-class="????">..</tr> 

La méthode précédente ne fonctionnera pas car la méthode "foo" est définie sur responseData et NOT on item object

Existe-t-il un moyen d'étendre directement la classe de base utilisée pour l'instanciation d'objets sur la liste?

Merci!

J'ai trouvé ce problème avant, et la solution semble être transformResponse , comme le dit John Ledbetter dans l'autre réponse.

Quoi qu'il en soit, si vous devez conserver l'objet entier et avoir le tableau dans les «éléments» remplis d'instances de la ressource, vous pourriez le faire avec l'astuce suivante:

Prenant l'exemple de la réponse de John, et en le modifiant un peu:

 angular.module('foo') .factory('Post', ['$resource', function($resource) { var Post = $resource('/api/posts/:id', { id: '@id' }, { query: { method: 'GET', isArray: false, // <- not returning an array transformResponse: function(data, header) { var wrapped = angular.fromJson(data); angular.forEach(wrapped.items, function(item, idx) { wrapped.items[idx] = new Post(item); //<-- replace each item with an instance of the resource object }); return wrapped; } } }); Post.prototype.foo = function() { /* ... */ }; return Post; }]); 

Si vous utilisez la ressource angulaire 1.1.5 (qui, dans la mesure où je peux le dire, fonctionne bien avec le 1.0.7 angulaire), il existe une option transformResponse vous pouvez spécifier lors de la substitution $resource méthodes de $resource :

 angular.module('foo') .factory('Post', ['$resource', function($resource) { var Post = $resource('/api/posts/:id', { id: '@id' }, { query: { method: 'GET', isArray: true, transformResponse: function(data, header) { var wrapped = angular.fromJson(data); return wrapped.items; } } }); Post.prototype.foo = function() { /* ... */ }; return Post; }]); 

Si vous faites cela, vous n'avez plus à supprimer manuellement les éléments de la réponse emballée, et chaque élément sera une instance de Post qui a accès à la méthode .foo . Vous pouvez simplement écrire:

 <tr ng-repeat="post in posts" ng-class="{warning: post.foo()}">..</tr> 

L'inconvénient à cela est que vous perdez l'accès à l'un des champs extérieurs dans votre réponse qui ne sont pas à l'intérieur des objets. Je suis toujours en train de trouver un moyen de préserver ces métadonnées.

C'est une vieille question, mais je viens de rencontrer cette question moi-même. La solution de gargc est la bonne approche, mais il y a une amélioration. transformResponse accepte un tableau qui passe au service $http . Plutôt que de remplacer complètement la fonction de transformation, vous pouvez ajouter votre transformée aux valeurs par défaut pour simplement effectuer les mises à jour dont vous avez besoin:

 angular.module('foo') .factory('Post', function ($resource, $http) { var Post = $resource('/api/posts/:id', { id: '@id' }, { query: { method: 'GET', isArray: false, transformResponse: $http.defaults.transformResponse.concat(function(data, header) { angular.forEach(data.items, function(item, idx) { data.items[idx] = new Post(item); }); return data; }) } }); Post.prototype.foo = function() { /* ... */ }; return Post; }); 

Vous pouvez placer les métadonnées dans un en-tête. J'ai toujours mis des données de pagination là. De cette façon, votre requête renverra toujours un tableau, ce qui, je le crois, est une bonne chose. Les requêtes doivent renvoyer des tableaux de données, pas de données uniques.