从下拉菜单选择中动态添加表单

时间:2014-08-20 00:10:58

标签: javascript jquery ruby-on-rails ruby

我有一个关于通过下拉选择添加动态表单的Ruby on Rails问题,而不是为每个可能的选择添加单独的按钮。

现在,通过关注一些Railscast的帮助,我的应用程序可以在三个单独的按钮上工作,这三个按钮能够动态地向父级添加三种不同类型的嵌套表单,所有这些按钮都对应于具有不同形式部分的不同模型。 / p>

这里的父模型是一个Workout,允许使用JS动态添加traditional_blocks,emon_blocks和tempo_blocks。

锻炼模型

class Workout < ActiveRecord::Base
  has_many :tempos
  has_many :traditionals
  has_many :emons
  accepts_nested_attributes_for :tempos, allow_destroy: true
  accepts_nested_attributes_for :emons, allow_destroy: true
  accepts_nested_attributes_for :traditionals, allow_destroy: true
end

/app/views/workouts/new.html.erb

<div>   
    <%= button_to_add_fields "Add EMON Block", f, :emons %>
    <%= button_to_add_fields "Add traditional Block", f, :traditionals %>
    <%= button_to_add_fields "Add tempo Block", f, :tempos %>
</div>

/apps/helpers/application_helper.rb

module ApplicationHelper
  def button_to_add_fields(name, f, association)
    new_object = f.object.send(association).klass.new
    id = new_object.object_id
    fields = f.fields_for(association, new_object, child_index: id) do |builder|
      render(association.to_s.singularize + "_fields", f: builder)
    end
    button_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
  end
end

应用程序/资产/ Javascript角/ workouts.js.coffee

$(document).on 'click', 'form .add_fields', (event) ->
  time = new Date().getTime()
  regexp = new RegExp($(this).data('id'), 'g')
  $(this).before($(this).data('fields').replace(regexp, time))
  event.preventDefault()

就像我之前说过的,当我点击按钮时,一切都按照我想要的方式工作。但是,我希望能够将“emon block,传统块,节奏块”放在collection_select中,并在collection_select旁边显示“create”旁边的一个按钮。当单击“创建”按钮时,我希望它调用相同的帮助程序(button_to_add_fields)传递必要的参数,使其工作方式与现在使用多按钮实现相同,但使用集合中当前选定的关联选择。

任何提示?

1 个答案:

答案 0 :(得分:0)

您需要Ajax用于此

您查看过的Railscast虽然很有帮助,但它每次只允许您添加单个嵌套表单的方式有些受限

-

<强>的Ajax

#config/routes.rb
resources :workouts do
   get "ajax_fields/:type", on: :collection
end

#app/models/workout.rb
Class Workout < ActiveRecord::Base
    ...
    def self.build type
       workout = self.new
       if type
          workout.send(type).build
       else
          workout.tempos.build
          workout.traditionals.build
          workout.emons.build
       end
    end
end

#app/controllers/workouts_controller.rb
Class WorkoutsController < ApplicationController
   def ajax_update
       @workout = Workout.build params[:type]
       render "form", layout: !request.xhr?
   end
end

#app/views/workouts/_form.html.erb
<%= form_for @workout do |f| %>
   <%= render "fields", locals: { f: f  }, onject: params[:type] %>
   <%= f.submit %>
<% end %>

#app/views/workouts/_fields.html.erb
<%= f.fields_for type.to_sym, child_index: Time.now.to_i do |t| %>
    <%= t.text_field :your_field %>
<% end %>

#app/views/workouts/new.html.erb
<%= form_for @workout do |f| %>
   <%= render: "fields", locals: { f: f}, collection: ["tempos", "traditionals", "emons"], as: :type %>
   <%= ... dropdown code ...%>
   <%= f.submit %>
<% end %>

-

这将允许您发送以下ajax请求:

#app/assets/javascripts/workouts.js.coffee
$(document).on 'change', 'form .add_fields', (event) ->
  type = $(this).val
  $.ajax
     url: "/workouts/ajax_fields/" + type,
     success: function(data) {
        $("form").append(data); // will have to work this out properly
     }
});

这应该使您能够将所需的额外字段附加到应用程序,然后将返回适当的HTML以便附加到DOM

希望你能在这里欣赏这种情绪 - 它可能无法立即使用!