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

Adding Forms Dynamically From Dropdown Menu Selection

本文关键字:添加 表单 动态 选择 下拉菜单      更新时间:2023-09-26

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

现在,通过一些railscast的帮助,我的应用程序工作在我有三个单独的按钮,能够动态地将三种不同类型的嵌套表单添加到父控件中,它们都对应于具有不同表单部分的不同模型。

这里的父模型是一个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/训练/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>

引入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块,传统块,节奏块"内的collection_select一个按钮旁边的collection_select说"创建"。当"创建"按钮被单击时,我希望它调用相同的帮助器(button_to_add_fields),传递必要的参数,使其工作方式与现在的多按钮实现相同,但使用当前选择的集合选择中的关联。

提示吗?

您将希望使用Ajax作为此

您所查看的Railscast虽然很有帮助,但在某种程度上是有限的,它只允许您每次添加单个嵌套表单

,

#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

中。

希望你能理解这里的情绪-它可能无法立即开箱工作!