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

mig*_*jek 37 javascript angularjs angularjs-resource

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

var Data = $resource('http://..');
Data.prototype.foo = function() {return ...};
Run Code Online (Sandbox Code Playgroud)

这非常适合与ng-repeat/ng-class一起使用,如下所示:

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

我的问题是每个列表响应都封装在一个对象中,除了实际列表之外,它还有一些元属性(排序信息等),所以返回的最终对象是这样的:

{ order_field: "name", items: [{..}, {..},{..}] }
Run Code Online (Sandbox Code Playgroud)

现在,我如何使用ng-repeat/ng-class进行与之前相同的操作?

<tr ng-repeat="item in responseData.items" ng-class="????">..</tr>
Run Code Online (Sandbox Code Playgroud)

之前的方法不起作用,因为定义了"foo"方法responseData而不是item对象

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

谢谢!

gar*_*rst 53

我之前发现了这个问题,解决方案似乎transformResponse正如John Ledbetter在另一个答案中所说的那样.

无论如何,如果你需要保留整个对象,并且在'items'中的数组中填充了资源的实例,那么你可以使用以下技巧来完成它:

以John的答案为例,并稍微修改一下:

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;
  }]);
Run Code Online (Sandbox Code Playgroud)


Joh*_*ter 9

如果你正在使用angular-resource 1.1.5(据我所知它实际上可以正常使用角度1.0.7),transformResponse你可以在覆盖$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;
  }]);
Run Code Online (Sandbox Code Playgroud)

如果这样做,您不再需要手动从包装的响应中提取项目,并且每个项目都是可以Post访问该.foo方法的实例.你可以写:

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

这样做的缺点是您无法访问响应中不在项目内部的任何外部字段.我仍然在努力想出一种保存元数据的方法.