【问题标题】:Angular - extending $resource subobject with custom methodsAngular - 使用自定义方法扩展 $resource 子对象
【发布时间】:2013-06-12 15:10:53
【问题描述】:

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

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

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

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

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

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

现在,如何使用 ng-repeat/ng-class 制作与以前相同的东西?

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

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

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

谢谢!

【问题讨论】:

    标签: javascript angularjs angularjs-resource


    【解决方案1】:

    我以前发现过这个问题,解决方案似乎是 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;
      }]);
    

    【讨论】:

    • 我认为这是一个可靠的解决方案。我觉得它不是完美,但它是我见过的最好的:)
    【解决方案2】:

    如果您使用的是 angular-resource 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>
    

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

    【讨论】:

    • 谢谢,但这并不是我真正想要的。当我同时编写 angular-js 前端和 C#-后端时,我可以简单地避免将列表包装在对象中,但重点是我也需要该元数据。
    • @migajek 我明白,我处于同样的情况——我希望能够使用我的 API 支持分页/排序,而不必手动“拆箱”所有资源。有兴趣看看是否有任何好的答案。
    • 我通过添加闭包变量 function(){ var meta = {}; 来添加元数据。 var Product = $resource = {transformResponse : function(data) { meta.prop = data.prop;} } Product._meta = meta;退货; }
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-10
        • 2019-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多