角度资源 - 默认模型结构

时间:2014-12-02 13:48:53

标签: angularjs angularjs-resource

因此我使用此Rest API与ngResource进行获取查询发布更新请求。我正在寻找的是一种为每个实体定义结构的方法。

例如,假设我们有:

module.factory('app.entity.item', function($resource) {
    return $resource('http://xmpl.io/items/:itemId', { itemId: '@id' });
});

我想在控制器中实例化它,如:

module.controller('AddItemCtrl', ['app.entity.item', function(Item) {
    $scope.item = new Item();
});

并将其绑定到我模板中的相应表单。

我遇到的实际问题是,我必须处理1:m表。 实体结构的一个例子是:

{
  "name": "",
  "categories": [],

  "list": [
    {
      "value": "",
      "list": [
        {
          "value": "",
          "list": [
            {
              "value": ""
            }
          ]
        }
      ]
    }
  ]
}

(以下小提琴中的更全面的例子)

现在前两个字段显然不是问题。这是第三个。 listadd(type, context)。这些列表中的每一个都可以包含可变数量的项目。

我目前正在使用ngRepeat和value方法,该方法向范围(此示例中的module.controller('AddItemCtrl', ['app.entity.item', function(Item) { $scope.item = new Item({ "name": "", "categories": [], "list": [ { "value": "", "list": [ { "value": "", "list": [ { "value": "" } ] } ] } ] }); }); 字段和前两个级别的子列表)添加了一组新字段,这些字段将出现在UI中通过ngRepeat使用户可以填写并提交给服务。

首先,我必须定义结构,因此在页面加载时UI不会为空。

item.$save

但这是多余的。我到处都要做! 另一个问题是,当调用{{1}}时,模型被清空(可能重新实例化?),list属性中的字段(由ngRepeat指令管理)消失了。

所以我想知道,在这种情况下你会做什么。 有没有办法定义实体(资源)结构?

示例:http://jsfiddle.net/g15sqd5s/3/

2 个答案:

答案 0 :(得分:1)

尝试给出简单的答案 - 对于简单的结构,我会使用像

这样的东西
module.factory('Item', function($resource) {
  var resource = $resource('http://xmpl.io/items/:itemId', { itemId: '@id' },
    // you can also define transformRequest here: 
    { transformRequest: function(data) {
      // data can be transformed here
      return angular.toJson(data);
    }});

  return angular.extend(resource.prototype, 
    {
       name: null,
       categories: []
    });
  });

然后要注意'flatten' the object的必要性。

对于更复杂的模型,我会检查restangular

此处还讨论了类似的主题: How can I extend the constructor of an AngularJS resource ($resource)?

答案 1 :(得分:0)

我会继续在后端修改我的模型结构 - 客户端的模型应该只遵循已经定义的模型,而不是在变换块中重新定义。因此,为了回答您的问题,“默认”模型结构来自服务器。您在$resource对象中获得的内容具有服务器返回的结构。

首先,当用户填充了某些值时,是否可以在$save模型上调用Item?我们想要保存的内容显然是与项目关联的列表,而不是项目本身。在后端定义的单独资源,例如items/<item_id>/list,可能是一个更清洁的解决方案。它可能无法很好地扩展,因为您必须为每个项目单独GET请求获取其列表,但这是正确的RESTful方式。

将这种方法扩展到您的小提琴中的示例,我想像buildings/<building_id>/floors/<floor_id>/units/<unit_id>这样的路由方案将是一个合适的解决方案。向GET发出buildings/请求会产生一系列建筑物;返回的数组中的每个构建都应该是Building模型的实例,该模型具有正确的URL集,因此用户可以执行单个POST并仅更新构建名称,而不是发回整个结构回到服务器。将此递归应用于嵌套资源应该为您提供一种简洁明了的方法来处理模型更改。

关于UI部分 - 我将继续为建筑物,楼层和单元定义三个指令,并让每个指针管理具有相应资源的数组,同时注意UI绑定到模型值。

那么Building模型怎么样?

var BuildingResource = $resource('/buildings/:id', { id: '@id' });

调用BuildingResource.query()应该会产生一系列现有建筑物。添加新建筑可能如下所示:

var newBuilding = new BuildingResource();
newBuilding.$save().then(function(building) {
  $scope.buildings.push(building);
}, function(errData) {
  //Handle error here...
});

为其余资源扩展此模式应该很容易 - 请注意,服务器需要为每个建筑物返回的内容只是nameid;知道id足以构造一个URL(和$resource对象),以获取所需的子资源(在本例中为楼层)。