2015-09-01 54 views
1

我有些困难。我在AngularJS中使用Rails 4.2.3。我有一个表单需要上传相关数据模型的嵌套属性,并且还要上传图像。正如我发现,使用AJAX请求上传文件不是一件容易的事,我使用ng-file-upload来解决这个问题,但是我有一些基本的使用问题。AngularJS - 具有Rails嵌套属性的ngFileUpload

我的Rails型号:

class Job < ActiveRecord::Base 
    has_many :references, dependent: :destroy 
    accepts_nested_attributes_for :references, limit: 5 
end 

class Reference < ActiveRecord::Base 
    belongs_to :job 
end 

Rails的预计提交表单时,格式如下:

Parameters: {"job"=>{"title"=>"Example Title", "company"=>"Example Company", "description"=>"Example Description", "references_attributes"=>{"0"=>{"reference"=>"Example Reference", "id"=>"1"}}, "image"=> #plus the image data here} 

随着NG-文件上传,看来几乎是不可能的,包括嵌套属性(或者也许我我错过了一些东西,我已经多次阅读文档以试图找到这方面的任何东西)。我采用了这种有点疯狂的方式,以Rails可以理解的方式包含嵌套属性。以下表格:

<div class="row"> 
    <div class="col-md-6 col-md-offset-3"> 
    <form ng-submit="save(job)" accept-charset="UTF-8" enctype="multipart/form-data"> 
     <label for="job_title">Title</label> 
     <input ng-model="job.title" 
      class="form-control" 
      id="job_title" 
      name="job[title]" 
      type="text" 
     required /> 
    <div ng-repeat="error in errors.title" class="alert alert-danger">Title {{error}}</div> 

    <label for="job_company">Company</label> 
    <input ng-model="job.company" 
     class="form-control" 
     id="job_company" 
     name="job[company]" 
     type="text" 
     required /> 
    <div ng-repeat="error in errors.company" class="alert alert-danger">Company {{error}}</div> 

    <label for="job_years">Years</label> 
    <input ng-model="job.years" 
     class="form-control" 
     id="job_years" 
     name="job[years]" 
     type="text" /> 
    <div ng-repeat="error in errors.years" class="alert alert-danger">Years {{error}}</div> 

    <label for="job_manager">Manager</label> 
    <input ng-model="job.manager" 
     class="form-control" 
     id="job_manager" 
     name="job[manager]" 
     type="text" /> 
    <div ng-repeat="error in errors.manager" class="alert alert-danger">Manager {{error}}</div> 

    <label for="job_contact">Contact</label> 
    <input ng-model="job.contact" 
     class="form-control" 
     id="job_contact" 
     name="job[contact]" 
     type="text" /> 
    <div ng-repeat="error in errors.contact" class="alert alert-danger">Contact {{error}}</div> 

    <label for="job_address">Address</label> 
    <input ng-model="job.address" 
     class="form-control" 
     id="job_address" 
     name="job[address]" 
     type="text" /> 
    <div ng-repeat="error in errors.address" class="alert alert-danger">Address {{error}}</div> 

    <label for="job_description">Description</label> 
    <textarea ng-model="job.description" 
      class="form-control" 
      id="job_description" 
      name="job[description]" 
      required> 
    </textarea> 
    <div ng-repeat="error in errors.description" class="alert alert-danger">Description {{error}}</div> 

    <label for="job_skills">Skills</label> 
    <input ng-model="job.skills" 
     class="form-control" 
     id="job_skills" 
     name="job[skills]" 
     type="text" /> 
    <div ng-repeat="error in errors.skills" class="alert alert-danger">Skills {{error}}</div> 

    <label for="job_references">References</label> 

    <input ng-model="job.references[0]" 
     class="form-control" 
     id="job_references_attributes_0_reference" 
     name="job[references_attributes][0][reference]" 
     type="text" /> 

    <input ng-model="job.references[1]" 
     class="form-control" 
     id="job_references_attributes_1_reference" 
     name="job[references_attributes][1][reference]" 
     type="text" /> 

    <input ng-model="job.references[2]" 
     class="form-control" 
     id="job_references_attributes_2_reference" 
     name="job[references_attributes][2][reference]" 
     type="text" /> 

    <input ng-model="job.references[3]" 
     class="form-control" 
     id="job_references_attributes_3_reference" 
     name="job[references_attributes][3][reference]" 
     type="text" /> 

    <input ng-model="job.references[4]" 
     class="form-control" 
     id="job_references_attributes_4_reference" 
     name="job[references_attributes][4][reference]" 
     type="text" /> 

    <label for="job_image">Image</label> 
    <input ng-model="job.image" 
     class="width-100" 
     id="job_image" 
     name="job[image]" 
     type="file" 
     ngf-select 
     accept="image/*" 
     ngf-max-size="5MB" /> 
    <div ng-repeat="error in errors.image" class="alert alert-danger">Image {{error}}</div> 

    <div class="center"> 
    <div class="btn-group"> 
     <input class="btn btn-large btn-primary" 
       name="commit" 
       type="submit" 
       value="Submit" /> 
     </div> 
     <div class="btn-group"> 
      <a ng-click="back()" href class="btn btn-large btn-default">&larr; Cancel</a> 
     </div> 
     </div> 
    </form> 
    </div> 
</div> 

的“哈克”位我指的是我已经有了“job.references [0]”怎么回事。下面是我如何与它有NG-文件上传的工作,包括嵌套属性:

$scope.save = function(job) { 
    var file = job.image; 
    Upload.upload({ 
    url: '/api/jobs/' + job.id, 
    method: 'PUT', 
    fields: { 
     'job[title]': job.title, 
     'job[company]': job.company, 
     'job[description]': job.description, 
     'job[years]': job.years, 
     'job[manager]': job.manager, 
     'job[contact]': job.contact, 
     'job[skills]': job.skills, 
     'job[address]': job.address, 
     'job[references_attributes][0][reference]': job.references[0], 
     'job[references_attributes][1][reference]': job.references[1], 
     'job[references_attributes][2][reference]': job.references[2], 
     'job[references_attributes][3][reference]': job.references[3], 
     'job[references_attributes][4][reference]': job.references[4] }, 
    file: file, 
    fileFormDataName: 'job[image]' 
    }).progress(function (evt) { 
    $scope.progress = Math.min(100, parseInt(100.0 * evt.loaded/evt.total)); 
    console.log('Progress: ' + $scope.progress + '% ' + evt.config.file.name); 
    }).success(function (data, status, headers, config) { 
    console.log('File ' + config.file.name + 'uploaded. Response: ' + data); 
    $scope.jobs.push(data); 
    $state.go('jobs.show', {id: $stateParams.id}) 
    }).error(function (data, status, headers, config) { 
    console.log('Error status: ' + status); 
    $scope.errors = data; 
    }); 
} 

这非常适用于新的模式条目,但是当我在这里编辑现有条目是哪里出了问题..这是被发送到Rails的这种设置JSON数据:

Parameters: {"job"=>{"title"=>"Example Title", "company"=>"Example Company", "description"=>"Example Description", "references_attributes"=>{"0"=>{"reference"=>"Example Reference"}}, "image"=> #plus the image data here} 

正如你可能已经注意到了,不再被包含在嵌套的属性“id”属性。这导致Rails在我提交任何编辑时复制现有的嵌套属性。有没有人有更好的想法,我怎么可以包含ng-file-upload的嵌套属性?或者甚至没有ng-file-upload的解决方案?

在此先感谢!

+0

我没有看到任何ID属性上你的页面不知道究竟是什么问题。无论如何,你只需将你的json对象作为'data'而不是'fields'传递,它将以json字符串格式发送数据,然后在服务器上将接收到的数据字段的json字符串转换为json对象。 – danial

+0

@danial是的,这就是我想弄清楚如何包括。我想过在表单中​​包含ID输入字段,或者将它们包含在ng-file-upload的“字段”部分,问题就变成了,他们发送的ID数据没有任何“引用”属性的条目, Rails ...我会尝试你提到的'data'位。 –

+0

@danial是否有可能使用'data'而不将参数发送到服务器,就像'data => {params}'一样包装? –

回答

4

该工具最近有一个更新,它极大地帮助嵌套属性。对于这种使用Rails,嵌套的属性...在窗体中,您可以使用以下格式:

<input ng-model="Object.nested_attributes[0]" /> 

然后在AngularJS控制器:

 Upload.upload({ 
     url: 'RailsController#create or update path', 
     method: 'post or put', 
     data: { 
     YourDataModel: { 
      image: file, 
      nested_attributes: $scope.Object.nested_attributes 
     } 
     } 
    });