AngularJS:具有嵌套资源的 $resource

Posted

技术标签:

【中文标题】AngularJS:具有嵌套资源的 $resource【英文标题】:AngularJS: $resource with nested resources 【发布时间】:2014-11-14 10:52:51 【问题描述】:

我正在将 AngularJS $resource 模型用于 REST API。我有这样的东西:

angular.module('libraryapp')
    .factory('Book', function($resource)
        return $resource('books/:id');
    );

我是这样使用的:

Book.get( id: 42 , function(book) 
    console.log(book);
);

但我也想要一个子资源的端点,比如说:

GET /books/:id/comments

我应该如何在模块中定义它?我可以以某种方式扩展 Book,像这样使用它

Book.get( id: 42 ).Comment.query(function(comments) 
    console.log(comments);
);

【问题讨论】:

【参考方案1】:

您可以使用 AngularJS $resource 定义轻松访问嵌套的 RESTful 资源。

线索是了解$resource 定义中每个action 定义(在actions 列表中)的params 参数如何工作。正如文档所说,这是一个

此操作的可选预绑定参数集。 […]

angular.module('libraryApp').factory('Book', [
  '$resource', function($resource) 
    return $resource('books/:id/:subResource', , 
      comments:   // The `comments` action definition:
        params: subResource: 'comments',
        method: 'GET'
      
    );
  
]);

鉴于上述定义,您应该仍然可以像以前一样使用Book。例如Book.get( id: 42 ) 转换为GET books/42/ 请求。

但是,鉴于 $resource URL ('books/:id/:subResource') 的新 :subResource 部分,您现在可以生成一个

GET books/42/comments

通过调用 either Book.get( id: 42, subResource: 'comments' ) 或定义为您的 comments 操作的更简洁优雅的界面 Book.comments( id: 42 ) 来请求。

【讨论】:

我知道我回答得这么晚了,但是如果答案对你有用,那么如果你接受它作为答案会很棒——这样其他用户就可以从知道答案有效的过程中受益。如果您有任何问题,请告诉我。 这个解决方案的问题是返回的 cmets 将是 Book 资源的实例。所以如果我们调用Book.comments( id: 42 ).$promise.then(function (comments) comments[0].$get(); ); 那么这个$get 会尝试调用GET /books/<commend_id> 这当然是不对的。 djxak,你有解决这个问题的方法吗?【参考方案2】:

据我所知,你不能嵌套资源,但是做你正在寻找的东西非常简单:

您可以定义可以在每个资源中覆盖的可选参数(如 category 此处),甚至覆盖 url(查看 otherUrl 资源)

angular.module('libraryApp').factory('Book', [
  '$resource', function($resource) 
    return $resource('books/:id/:category', , 
      comments: 
        method: 'GET',
        action: 'category'
      ,
      otherUrls: 
        method: 'GET',
        url: 'books/:id/admin/:option'
      
    );
  
]);

【讨论】:

【参考方案3】:

您可能希望使用 Restangular,因为它可以处理嵌套资源并且是一种干净且简单的方法。

【讨论】:

【参考方案4】:

正如 djxak 所指出的,向资源添加动作意味着返回值是包含资源类型,而不是子资源类型。

我通过使用子资源 URL 创建新资源并修改包含资源的原型以添加功能解决了类似的问题:

angular.module('libraryapp')
    .factory('Book', function($resource)
        var bookUrl = 'books/:id',
            Book = $resource(bookUrl),
            BookComment = $resource(bookUrl + /comments");

        Book.prototype.getComments = function () 
            return BookComment.query(id: this.id);
        ;

        return $resource('books/:id');
    );

那么用法就变成了:

Book.get( id: 42 ).getComments(function(comments) 
    console.log(comments);
);

我看到这种方法的唯一缺点是,如果您有一个通过不同 URL 访问的单独的“评论”资源,则必须为替代端点复制 $resource 初始化代码。不过,这似乎有点不便。

【讨论】:

以上是关于AngularJS:具有嵌套资源的 $resource的主要内容,如果未能解决你的问题,请参考以下文章

angularJS 1.5 嵌套组件

spring配置加载maven项目里面的src/main/resoures下的静态资源,配置路径是file:

如何在 AngularJS 中设置嵌套视图?

具有嵌套资源的 AFRESTClient pathForEntity?

Rails form_for 具有相同属性的嵌套和关联资源已填充文本

在 RESTful URL 中具有嵌套资源的父 ID 背后的合理性