【问题标题】:What is the preferable way to handle form submissions that have related models in AngularJS?在 AngularJS 中处理具有相关模型的表单提交的最佳方法是什么?
【发布时间】:2012-08-01 18:11:59
【问题描述】:

我的项目使用 AngularJS + Django Tasypie。我正在使用我在下面发布的 CoffeeScript 代码处理表单提交。由于我刚刚开始使用 Angular 进行开发,因此我想提出改进建议。也许使用服务和/或 $resource?请务必注意,“Project”实体具有 oneToMany“Client”关系。

谢谢。

通用模型类:

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

【问题讨论】:

    标签: coffeescript tastypie angularjs


    【解决方案1】:

    感觉就像你被一个数据实体一个路由挂断了,这可能源于你将序列化层耦合到数据模型。我建议你在这里重新考虑你的方法。这感觉像是缺乏动力的继承。

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

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

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

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

    更新

    我刚刚意识到您需要将客户端与项目 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']}]
    ]
    

    【讨论】:

      猜你喜欢
      • 2021-11-14
      • 2012-06-03
      • 2010-12-02
      • 2015-04-04
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多