简体   繁体   English

Rails使用JavaScript嵌套多态形式

[英]Rails nested polymorphic form with javascripting

I want the following on my form: 我要在表格上填写以下内容:

在此处输入图片说明

Degree is polymorphic partial with has_many relation to profile. 度是与轮廓具有has_many关系的多态部分。 This partial is called by main form - profile. 该部分称为主要形式-配置文件。 By pressing 'Add a Qualification' user can add as many degrees. 通过按“添加资格”,用户可以添加尽可能多的学位。 I've been able to attach only one degree to profile which is the last one others are all ignored. 我只能将一个学位附加到个人资料,而最后一个学位则全部被忽略。 I even know why it's happening because link_to is not able to pass profile instance. 我什至不知道为什么会这样,因为link_to无法传递配置文件实例。 so I have to create new profile in degrees_controller as you can see in my code here . 所以我必须在degree_controller中创建新的配置文件,如您在我的代码中看到的那样。 Can final profile instance pick up all others above when submitting 'Create Profile'. 提交“创建配置文件”时,最终的配置文件实例可以获取上述所有其他信息。

Kindly any help so that I can have all of the degrees attached with form, I'm stuck on this for last couple of days with all permutations and combinations from SO and google. 请提供任何帮助,以便我可以将所有学位与形式相关联,在过去的几天中,我一直坚持使用SO和google的所有排列组合。 I'm ready to change code even....any help with this will be appreciated. 我已经准备好更改代码了。任何对此的帮助将不胜感激。

I've got this little helper to get me through these cases. 我有这个小帮手来帮助我解决这些情况。 Its reusable so you don't ever have to write all this stuff for different cases in the same app. 它可重复使用,因此您不必在同一应用程序中针对不同情况编写所有这些东西。

First the code: 首先是代码:

module FormsHelper

  def data_for_field(f, subclass, options={})
    new_object = f.object.class.new.send(subclass.to_s).new(options[:attributes])
    id = new_object.object_id
    partial_path = options[:path] || new_object
    fields = f.fields_for(subclass, new_object, child_index: id) do |builder|
      render(partial_path, f: builder)
    end
    {id: id, fields: fields.gsub("\n", "")}
  end

end

Some JS magic: 一些JS魔术:

$(document).on('click', '.add-fields', function(e){
  var time = new Date().getTime();
  var regexp = new RegExp($(this).data('id'), 'g');
  var content = $(this).data('fields').replace(regexp, time);
  $(target).append(content);
  e.preventDefault();
});

Now a view call: 现在进行视图调用:

<%= form_tag .... do |f|
    <div id="list"></div>
    <%= link_to 'Add an Organisation', '#', class: 'add-fields', data: data_for_field(f, :degrees, path: "/degrees/fields").merge(target: "#list") %></p>
<% end %>

Now create a partial where the degree fields to use. 现在,在要使用的度数字段中创建局部的。

/degrees/_fields.html.erb /degrees/_fields.html.erb

<%= content_tag :div do %>
  <%= f.input :name %>
<% end %>

Now the explanation: 现在说明:

For data_for_field you pass: f (form), :degrees (the plural name of the associated model as a symbol), and any additional options like the path to the partial for the fields. 对于data_for_field,您传递:f(形式),:degrees(关联模型的复数名称作为符号),以及任何其他选项,例如字段局部的路径。 It basically creates a scaffold of the form fields and sets them as a data attribute on the "Add Qualification" link. 它基本上创建了表单字段的支架,并将其设置为“添加资格”链接上的数据属性。 I've merged in a data-target which has the css ID of where to insert the new fields into the page as well. 我已经合并到一个数据目标中,该目标具有在其中将新字段插入页面的CSS ID。

When you click the JS event fires and replaces the id in the form fields with a timestamp so for each qualification you'll have a unique key. 当您单击JS事件时,系统会触发JS事件,并将表单字段中的ID替换为时间戳,因此对于每个资格,您都有一个唯一的密钥。

I also usually have a little extra JS event for removing the fields as well. 我通常也有一些额外的JS事件,用于删除字段。

Hope this helps. 希望这可以帮助。

This is a polymorphic nested association and can be handled on client side with javascript. 这是一个多态嵌套关联,可以在客户端使用javascript处理。 So, finally for nested fields I used the plugin Numerous.js . 因此,最后对于嵌套字段,我使用了插件Numerous.js Just follow as the steps given in the qucikstart part of link by downloading the numerous.js file from the Github and saving to assets/javascripts. 只需按照链接的qucikstart部分中给出的步骤进行操作,即从Github下载many.js文件并将其保存到资产/ javascript。

In my code, 在我的代码中

profile.rb profile.rb

class Profile < ApplicationRecord
  has_many :degrees, :as => :degreeable
  accepts_nested_attributes_for :degrees, :reject_if => :all_blank, allow_destroy: true

  belongs_to :user, :class_name => 'User', :foreign_key => 'user_id'
end

degree.rb degree.rb

class Degree < ApplicationRecord
   belongs_to :degreeable, polymorphic: true
end

profiles/_form.html.erb 型材/ _form.html.erb

    <div id="fields-for-list" class="numerous">
      <%= f.fields_for :degrees, Degree.new, :child_index => 'replace_this' do |degree_form| %>
         <%= degree_form.select :level, options_for_select(Job::EDUCATION, params[:level]), include_blank: "Select Degree", :class => 'span5' %>
         <%= degree_form.text_field :description, placeholder: "Add a new Degree here..."%>
         <%= link_to 'x Remove', '#', :class => 'numerous-remove', type: 'button' %>
     <% end %>
   </div>
   <div id="list"></div>
   <%= link_to (fa_icon 'plus').to_s + 'Add a Qualification', '#', :id => 'add-to-list' %>

and finally, with strong parameters, 最后,有了强大的参数,

  def profile_params
    params.require(:profile).permit(:user_id, :first_name, :last_name, degrees_attributes:[:id, :level, :description])
  end

Note that I had already set-up degree table with 2 extra fields for polymorphic association:- "degreeable_id" & "degreeable_type" and when entering in DB, the two fields were automatically filled with newly created profile_id and 'Profile'(the name of the model which is associating polymorphically with degree). 请注意,我已经设置了度数表,其中有2个额外的字段用于多态关联:- "degreeable_id" & "degreeable_type"并且在输入数据库时​​,这两个字段会自动填充新创建的profile_id和'Profile'(名称为将多态与度相关联的模型)。

The trick in numerous.js is creating each nested form record(here degree) with unique temporary id such as Time.now.to_i so now each degree record created/destroyed at client side will have a diff degree_attribute 'id'. many.js中的技巧是使用唯一的临时ID(例如Time.now.to_i)创建每个嵌套的表单记录(此处为度),因此现在在客户端创建/销毁的每个度记录都将具有一个diff degree_attribute'id'。 Hope it helps others. 希望它能帮助别人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM