通过ajax渲染嵌套属性的编辑表单(通过jquery-fileupload上传图像)

时间:2014-01-30 22:12:41

标签: ruby-on-rails nested-forms jquery-file-upload

我有2个型号:

  1. 建筑→has_many :building_views
  2. BuildingView→belongs_to :building
  3. 我只能为现有建筑创建BuildingView - 通过编辑形式的建筑 BuildingView具有imagetitle属性。图像通过Carrierwave上传 工作流程:

    1. 我去编辑建筑页面
    2. 我有file_field允许选择多个文件
    3. 我选择的图片很少,他们通过jquery-fileupload-rails gem上传(为每张图片创建BuildingView)
    4. 上传后,它们会出现在编辑表单中(无需重新加载页面),并带有拇指和输入字段以编辑BuildingView的标题
    5. 1,2和3都可以。图片正在上传,BuildingView正在创建,页面重新加载后,它们会显示在“建筑物的编辑”窗体中,带有标题编辑输入字段(也可以成功编辑)。 4的问题:我无法通过ajax附加BuildingView编辑表单。

      这是我的档案:

      控制器/管理/ buildings_controller.rb

      # other defs ...
      
      def edit
        @building = Building.find(params[:id])
      end
      
      def update
        @building = Building.find(params[:id])
          if @building.update_attributes(building_params)
            flash[:success] = 'Woohoo!'
            redirect_to admin_buildings_url
          else
            render :edit
          end
      end
      
      # other defs ...
      
      private
        def building_params
          params.require(:building).permit(:all_building_params,
                                            building_views_attributes: [
                                              :_destroy,
                                              :id,
                                              :building_id,
                                              :image,
                                              :title
                                            ])
        end
      

      views / admin / buildings / edit.html.haml

      %h1 Edit building
      = form_for [:admin, @building] do |f|
        = render 'admin/buildings/form', f: f
        .form-element-container
          .form-element.b-form-labels  
          .form-element.b-form-fields
            = f.submit 'Edit building'
            = link_to t('admin.cancel'), :back
      
      = form_for [:admin, BuildingView.new] do |f_bv|
        = f_bv.hidden_field :building_id, value: @building.id
        = f_bv.file_field :image, multiple: true, name: 'building_view[image]'
      

      views / admin / buildings / _form.html.haml

      // fields for Building...
      
      #building_views
        .form-element-container
          .form-element
            %h2 Building views
      
      = f.fields_for :building_views do |bv_form|
        = render 'admin/buildings/form_building_views', f: bv_form
      

      views / admin / buildings / _form_building_views.html.haml

      .form-element-container
        .form-element.b-form-labels Image:
        .form-element.b-form-fields= image_tag(f.object.image_url(:thumb)) if f.object.image
      
      .form-element-container
        .form-element.b-form-labels Title:
        .form-element.b-form-fields= f.text_field :title
      

      assets / javascript / admin / buildings.js.coffee

      jQuery ->
        $('#building_view_image').fileupload(
          dataType: 'script'
        )
      

      控制器/管理/ building_views_controller.rb

      class Admin::BuildingViewsController < ApplicationController
      
        def create
          @building_view = BuildingView.create(building_view_params)
        end
      
        private
      
          def building_view_params
            params.require(:building_view).permit(:building_id, :image)
          end
      
      end
      

      views / admin / building_views / create.js.haml

      - if @building_view.new_record?
        == alert('Oops!');
      - else
        == $('#building_views').append('#{j render('admin/buildings/form_building_views')}');
      

      我选择要上传的文件→来自控制台的错误:

      ActionView::Template::Error (undefined local variable or method `f' for #<#<Class:0x007ffaa52faad8>:0x007ffaa7393970>):
      

      所以当我在 views / admin / building_views / create.js.haml 中呈现编辑表单时,我需要传递f
      但我无法弄清楚如何。我试过了:

      j render('admin/buildings/form_building_views', f: @building_view)
      

      但:

      ActionView::Template::Error (undefined method `object' for #<BuildingView:0x007ffaa738a348>):
      

1 个答案:

答案 0 :(得分:0)

好吧,就我所知,我无法将此f传递给此部分。所以我手动重新创建了部分。

<强>视图/管理/建筑物/ _form_building_views_ajax.html.haml

.form-element-container
  .form-element.b-form-labels= image_tag(@building_view.image_url(:thumb)) if @building_view

  .form-element.b-form-fields= text_field_tag "building[building_views_attributes][#{building_nested_model_count(@building_view, @building)}][title]", nil, placeholder: 'Title'

= hidden_field_tag "building[building_views_attributes][#{building_nested_model_count(@building_view, @building)}][id]", @building_view.id

我刚刚重新创建了表单,使用fields_for帮助程序生成了rails。 那里有新助手:building_nested_model_count(@building_view, @building) - 它计算当前BuildingViews的{​​{1}}金额。我将其用于Building哈希(请参阅paramsid输入字段参数)。

我需要更新3个文件。

  1. 定义@building
  2. <强>控制器/管理/ building_views_controller.rb

    name
    1. 添加class Admin::BuildingViewsController < ApplicationController def create @building_view = BuildingView.create(building_view_params) @building = @building_view.building end private def building_view_params params.require(:building_view).permit(:building_id, :image) end end 帮助
    2. <强>助手/管理/ building_views_helper.rb

      building_nested_model_count
      1. 并为ajax渲染部分切换
      2. <强>视图/管理/ building_views / create.js.haml

        module Admin::BuildingsHelper
        
            def building_nested_model_count(nested_var, building)
                nested_class = nested_var.class
                nested_class.where(building_id: building.id).count
            end
        
        end
        

        我不知道解决这个问题的好坏方法,但它确实有效:新的- if @building_view.new_record? == alert('Oops!'); - else == $('#building_views').append('#{j render('admin/buildings/form_building_views_ajax')}'); 表单正在呈现,而BuildingView在表单提交后保存到数据库。