2015-09-01 69 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 
     } 
     } 
    });