2014-12-02 70 views
0

所以我用这个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": "" 
      } 
      ] 
     } 
     ] 
    } 
    ] 
} 

(在下面的拨弄更透彻的例子)

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

我目前使用ngRepeat和add(type, context)方法,增加了一个新的字段集的范围(value场在这个例子中和孩子列出了前两个级别),这将是ngRepeat出现在用户界面,使用户可以填写并提交给服务。

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

module.controller('AddItemCtrl', ['app.entity.item', function(Item) { 
    $scope.item = new Item({ 
     "name": "", 
     "categories": [], 

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

但这是多余的。我必须到处去做! 另一个问题是调用item.$save时,模型被清空(可能重新实例化?),并且列表属性(由ngRepeat指令管理)中的字段消失了。

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

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

回答

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)?

+0

我没有看到transformRequest被用于什么;我不确定操纵原型,但它肯定是一个解决方案。 +1和参考。 – Fardin 2015-02-18 09:21:27

+0

transformRequest只是表明还有另一个机会来处理复杂/非标准的案例。 – ciekawy 2015-02-18 10:41:01

+0

啊哈!我意识到这一点,但我认为这不能解决我的问题。 – Fardin 2015-02-18 13:52:25

0

我会继续前进,在第一个地方后台修改我的模型结构 - 模型在客户端应该仅仅遵循已经定义的那些,而不是在变换块中重新定义。所以,要回答你的问题,“默认”模型结构来自服务器。你在$resource对象中得到的结果是你的服务器返回的结构。

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

将此方法扩展到您的小提琴示例中,我想象一个路由方案,如buildings/<building_id>/floors/<floor_id>/units/<unit_id>将是一个适当的解决方案。向buildings/发出GET请求会产生一个建筑物列表;返回数组中的每个建筑物应该是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对象)来获取所需的子资源(在本例中为floor)。

+0

模型不在重定义。我正在向用户提供一个表单来创建一个不存在的实体。我不相信我应该问服务器一个空的模型!你所说的“适当的RESTful方法来做到这一点”在我的jsfiddle例子中是完全正确的;但我们正在与一个单一的实体合作;另外,我们正在尽量减少请求。欢迎BTW。 – Fardin 2015-02-23 13:52:37

+0

在我的示例中没有单点要求服务器提供空模型。第二个代码片段在客户端创建一个模型,该模型可能包含任何需要的数据(例如名称)。 'POST'请求的响应然后被添加到范围数组中 - 它将包含从数据库返回的有效标识。如果您正在使用单个实体,那么原始查询中'1:m'是什么意思?这意味着,在单个“基础”实体的顶部,您将拥有一组实体。这正是所提出的方法所要处理的。 – 2015-02-23 14:33:35

+0

我的角度应用程序不关心服务器处理模型的方式;它只能看到一个实体。 (假设在这种情况下它是很有意义的!)我提到1:m让读者能够可视化结构。那是在我添加例子之前。 ---所提出的方法不能解决所提出的问题。我想生成一个表单。我没有看到如何拆分原始实体以包含其他实体的层次结构来帮助解决该问题。 – Fardin 2015-02-23 14:44:21