在AngularJS中处理具有相关模型的表单提交的首选方法是什么?

时间:2012-08-03 16:56:17

标签: coffeescript tastypie angularjs

我的项目使用AngularJS + Django Tasypie。我正在使用下面发布的CoffeeScript代码处理表单提交。由于我刚刚开始使用Angular开发,我想提出改进建议。也许使用服务和/或$资源?重要的是要注意“项目”实体具有oneToMany“客户”关系。

谢谢。

通用模型类:

class window.Model
    constructor: (options) ->
        @$scope = options.$scope
        @$http = options.$http
        @id = if options.id? then options.id

    fetch: (cb= ->) =>
        @$http.get(@url + '/' + @id).success (data) =>
            @toScope(data)
            cb(data)

    fetchAll: (cb= ->) =>
        @$http.get(@url).success (data) =>
        @toScopeAll(data)
        cb(data)

    save: (data, cb= ->) ->
        @update data, cb if @id? else @create data, cb

    create: (cb= ->) ->
        @$http.post(@url + '/', @fromScope()).success cb

    update: (cb= ->) =>
        @$http.put(@url + '/' + @id, @fromScope()).success cb

    remove: (cb= ->) ->
        @$http.delete(@url + '/' + @id).success cb

项目/客户端模型类:

    class window.ProjectModel extends Model
        url: '/api/project'

        toScope: (data) =>
            @$scope.project = data
            @$scope.client = @$scope.project.client.id

        fromScope: (data) =>
            id: @$scope.project.id
            name: @$scope.project.name
            client: id: @$scope.client


    class window.ClientModel extends Model
        url: '/api/client'

        toScopeAll: (data) =>
        @$scope.clients = [id: '0', name: 'Choose...'].concat data.objects

控制器代码:

window.ProjectCtrl = ($scope, $routeParams, $http) ->

    redirect = -> window.location = '#/projects'
    $scope.save = -> project.save redirect
    $scope.delete = -> project.remove redirect
    $scope.cancel = redirect

    $scope.client = '0'
    client = new ClientModel($scope: $scope, $http: $http)
    client.fetchAll()

    project = new ProjectModel($scope: $scope, $http: $http)

    if $routeParams.projectId?
        $scope.formType = 'update'
        project.id = $routeParams.projectId
        project.fetch()

1 个答案:

答案 0 :(得分:0)

感觉就像你在每个数据实体的一个路由上被挂起了,这可能源于你将序列化层与数据模型联系起来。我建议你在这里重新考虑你的方法。这感觉就像是缺乏动力的遗产。

尝试保持模型简单,无逻辑的JavaScript对象。然后,您应该使用一个适用于所有数据结构的序列化/持久层。尝试避免继承,这在这里没有帮助。根据经验,我更喜欢composition over inheritance

最后,您似乎需要进行批量交易。由于您的持久层现在是独立的,因此您可以修改持久层以一次更新多个javascript对象!然后,您可以在服务器上创建事务路由,接受类似于以下内容的数据结构:

[
  ['create', 'project', {project_name: ...}]
  ['create', 'client', {client_attrs}]
]

作为一个额外的好处,因为单个调用可以处理整个事务,所以如果其中一个操作失败了业务逻辑,则可以在服务器上处理回滚。

更新

我刚刚意识到您需要将客户端与project-id相关联。如果您可以在客户端上生成ID(使用UUID?),这种方法将按原样运行。

否则,您可以查看整个“嵌套属性”路径,在该路径中为嵌入客户端的项目提交数据结构,如下所示:

{
  project_name: "...",
  clients: [{client1_attrs}, ...]
}

这种方法经常被使用,但我不喜欢它,因为根据我的经验,它很少有效。 (您如何处理删除?您是否需要指定所有属性并每次更新每个关联的客户端?如果客户端与多个项目相关联怎么办?您可以看到它崩溃的速度有多快。)

我认为,鉴于UUID不可能,我希望采用的方法是让您的事务服务器控制器能够设置前面步骤返回的值:

此数据结构将告诉事务控制器在事务列表的第0个位置查找序列化的数据实体的字段“id”,并在序列化之前将其设置为此客户端的project_id。

[
  ['create', 'project', {project_name: ...}]
  ['create', 'client', {client_attrs}, {project_id: [0, 'id']}]
]