我有一个关于通过下拉选择添加动态表单的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)传递必要的参数,使其工作方式与现在使用多按钮实现相同,但使用集合中当前选定的关联选择。
任何提示?
答案 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
希望你能在这里欣赏这种情绪 - 它可能无法立即使用!