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