AngularJS $resource 和超媒体

7

我有一个 AngularJS 的 $resource 定义如下:

var Menus = $resource('http://cafe.com/api/menus');

以及RESTful API。因此,当我对菜单进行GET请求时,会返回以下内容:

<cafe>
  <collection href="http://cafe.com/api/menus" type="menus">
    <template>
      <data name="Name" prompt="Menu name" />
    </template>
    <items>
      <item href="http://cafe.com/api/menus/1">
        <link href="http://cafe.com/api/menus/1/ingredients" rel="ingredients" />
        <data name="Name" prompt="Menu name">Morning</data>
      </item>
      <item href="http://cafe.com/api/menus/2">
        <link href="http://cafe.com/api/menus/2/ingredients" rel="ingredients" />
        <data name="Name" prompt="Menu name">Happy Hour</data>
      </item>
    </items>
  </collection>
</cafe>

问题是,我如何删除菜单2?(假设它有自己的超媒体链接:http://cafe.com/api/menus/2

我宁愿不开始操作JS对象来提取ID。我不想让ID漂浮在我的代码中。我宁愿使用自引用项目href来发送DELETE请求。我支持,我在想每个项目是否都是一种“资源”对象类型?或者这对Angular来说要求太高了吗? - Greg
啊,当你说“删除”时,你是指通过HTTP在服务器上删除资源。据我所知,Angular不理解XML——一旦你的应用程序中的承诺被解决,Menus是什么(比如通过console.log)? - Michelle Tilley
我认为AngularJS不理解XML,因此我会假设整个XML文档作为一个字符串包含在单个$resource对象中。因此,您需要进行一些转换才能将其转换为有用的JS对象。实际上,我发现直接使用$http服务比$resource更容易,因为我发现$resource在错误处理方面过于高级且灵活性不足(尽管我承认,我对AngularJS还相当新,所以可能会错过一些东西)。 - Joe Dyndale
实际上这是JSON,我只是为了可读性而使用XML。是的,使用HTTP Delete动词从集合中删除“menu 2”。 - Greg
1
JSON对于我的咸巧克力眼球更易读。 - aycanadal
显示剩余2条评论
2个回答

11

假设你已经从XML转换成了一个由Angular管理的JavaScript对象数组,你可以使用以下代码渲染你的对象:

<tr ng-repeat="cafe in cafes">
    <td>{{cafe.name}}</td>
    <td>
        <button class="btn" ng-click="deleteCafe($index, cafe)">Delete</button>
    </td>
</tr>

在您的控制器中,您可以这样做:

function ListCtrl($scope, $http, CafeService) {
  CafeService.list(function (cafes) {
    $scope.cafes = cafes;
  });

  $scope.deleteCafe = function (index, cafe) {
    $http.delete(cafe.self).then(function () {
      $scope.cafes.splice(index, 1);
    }, function () {
      // handle error here
    });
  }
}

看,没有客户端创建URL的操作! :)

更新: 修复了splice命令中的一个bug,原本是splice(index, index),但应该是splice(index, 1)


似乎当您通过资源获取数组时,例如 var Menus = $resource('http://cafe.com/api/menus'); 并不意味着数组中的每个项目都是一个资源。因此,在这种情况下最好使用 $http... - Greg
1
@Greg - 不需要,只需像GET文档中所示设置isArray:true即可:http://docs.angularjs.org/api/ngResource.$resource - Trygve Laugstøl
是的,同意,当时没有注意到。 - Greg

2
如果您的REST服务向Angular返回JSON,并且JSON在返回的数据中包含菜单ID。
var Menu = $resource('http://cafe.com/api/menus/:id', { id: '@id' }); // replace @id with @<the id field in your json object>

// Delete menu 2
Menu.delete({id: 2}, function(){ // Success callback
  // Get all menus, 
  var menus = Menu.query(function() { // Success callback
    // alternative delete syntax:
    var lastMenu = menus.pop();
    lastMenu.$delete();
  });
});

如果可以的话,我不想在各个地方传递ID。资源应该位于给定的HREF位置。所以我想做的就是向给定的URL发送HTTP DELETE请求。也许我应该遍历菜单并实例化自定义菜单对象,并将HREF分配给对象上的属性... - Greg
1
是的,但我想知道是否可以将Menus数组中的每个“Menu”视为资源对象。因此,var menus = Menu.query(); 然后menus [0] . $ delete(); 是否可能? - Greg
1
是的,这就是我在演示中使用lastMenu的方式(menus.pop() 返回并移除数组的最后一个项目)。 - Guillaume86
1
@Greg - 这真的解决了你的问题吗?整个重点不是你不想依赖于客户端生成的URL吗?从我所看到的来看,这似乎是一种复杂的方式来执行'Menu[2].$delete();'。 - Trygve Laugstøl
看起来当你通过资源获取一个数组,比如 var Menus = $resource('http://cafe.com/api/menus'); 并不意味着数组中的每个项都是一个资源。因此,在这种情况下最好使用 $http...让资源表现得更加聪明会很好。也许一个新的超媒体模块的好主意。 - Greg
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接