Angular – 使用自定义方法扩展$ resource子对象

在大多数情况下, <custom-resource>.query()方法的结果是一个数组,可以使用以下(工厂)代码轻松扩展一些方法(业务逻辑):

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

这是使用ng-repeat / ng-class的最佳select,如下所示:

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

我的问题是, 每个列表响应封装在一个对象,除了实际的列表,有一些元属性(sorting信息等),所以返回的最后一个对象是这样的:

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

现在,我如何使用ng-repeat / ng-class来做同样的事情呢?

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

之前的方法将不起作用,因为“foo”方法是在responseData上定义的,而不是在item对象上定义的

有没有办法直接扩展用于实例化列表中的对象的基类?

谢谢!

我之前发现了这个问题,解决scheme似乎是transformResponse ,就像John Ledbetter在其他答案中所说的那样。

无论如何, 如果你需要保留整个对象 ,并且让'items'中的数组充满资源的实例,那么你可以用下面的方法来实现:

以约翰的答案为例,修改一下:

 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; }]); 

如果您使用的是angular度资源1.1.5(据我所知,实际上可以使用angular度1.0.7),在重写$resource方法时可以指定一个transformResponse选项:

 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; }]); 

如果你这样做,你不再需要从包装的响应中手动拉出项目,每个项目将是一个可以访问.foo方法的Post实例。 你可以写:

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

这样做的缺点是,您不能访问任何不在内部项目中的外部字段。 我仍然在努力想出一个方法来保存这个元数据。

这是一个古老的问题,但我自己也遇到过这个问题。 gargc的解决scheme是正确的方法,但有一个改进。 transformResponse接受传递给$http服务的数组。 您可以将变换追加到默认值,而不是完全replace变换函数,而只是进行所需的更新:

 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; }); 

您可以将元数据放在标题中。 我总是把分页数据放在那里。 这样你的查询仍然会返回一个数组,我相信这是一件好事。 查询应返回数据数组,而不是单个数据。