在带有 Cocoon 和 Rails 的每个嵌套 child object 上添加克隆按钮

Add clone button on each nested child object with Cocoon and Rails

我有一个 parent,我可以添加多个 children,我想在每个 child.

中添加一个带茧的克隆按钮

根据 我做了这个代码:

这些是模型:

class MantenimientoSetup < ApplicationRecord
  has_many :actuation_setups, inverse_of: :mantenimiento_setup, validate: true, autosave: true, dependent: :destroy
  accepts_nested_attributes_for :actuation_setups, allow_destroy: true, reject_if: :all_blank
end
class ActuationSetup < ApplicationRecord
  belongs_to :mantenimiento_setup, inverse_of: :actuation_setups
end

我必须从 child 部分中添加克隆按钮... parent and child form

但是每个新的 child 嵌套都需要这个按钮,如下所示: enter image description here

这些是 parent 和 child 部分:

<!-- views/mantenimiento_setups/_form.html.erb -->
<%= form_for @mantenimiento_setup do |f| %>
  ...
  ...
  ...

  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title">Configuraciones</h4>
    </div>
    <div class="panel-body mantenimiento-setup-element">
      <%= f.fields_for :actuation_setups do |act_setup_builder| -%>
        <%= render 'actuation_setup_fields', f: act_setup_builder %>
        <%= link_to_add_association 'Clone', f, :actuation_setups, data: {"association-insertion-node" => ".mantenimiento-setup-element", "association-insertion-method" => "append"}, wrap_object: Proc.new {|d| d = act_setup_builder.object.dup; d}, class: "btn btn-info btn-sm" %>
      <% end -%>
    </div>
    <div class="panel-footer">
      <%= link_to_add_fields 'Add new setup', f, :actuation_setups, {mantenimiento_setup: f.object}, {class: "btn btn-success", nested_form: "/mantenimiento_setups/actuation_setup_fields" }%>
    </div>
  </div>

  <%= save_button %>
<% end %>
<!-- views/mantenimiento_setups/_actuation_setup_fields.html.erb -->
<div class='row fields'>
  <div class="col-md-3 actuation-type-div-selector">
    
  ...
  ...
  ...

  <div class="col-md-1">
    <label class="control-label invisible">...</label><br/>
    <%= link_to_remove_fields "Remove", f%>
  </div>

</div>

如果我将克隆按钮粘贴到 child 部分,关闭以删除按钮...

<!-- views/mantenimiento_setups/_actuation_setup_fields.html.erb -->
<div class='row fields'>
  <div class="col-md-3 actuation-type-div-selector">
    
  ...
  ...
  ...

  <div class="col-md-1">
    <label class="control-label invisible">...</label><br/>
    <%= link_to_remove_fields "Remove", f%>
  </div>

  <div class="col-md-1">
    <label class="control-label invisible">...</label><br/>
    <%= link_to_add_association 'Clone', f, :actuation_setups, data: {"association-insertion-node" => ".mantenimiento-setup-element", "association-insertion-method" => "append"}, wrap_object: Proc.new {|d| d = act_setup_builder.object.dup; d}, class: "btn btn-info btn-sm" %>
  </div>
</div>

它 returns 这个错误是因为关联不存在,因为我从 child 调用到 child 关联:

Association actuation_setups doesn't exist on ActuationSetup

如何为每个 child 添加一个克隆按钮?

link_to_add_association 需要 parent(定义关联的地方)中的 form-object (f)。所以在嵌套级别,你需要知道 parent-form-object.

此外:如果记录已经存在,我们只想呈现 Clone 按钮。也许我应该更好地解释一下:表单和所有 Clone-partials 都在服务器上呈现,因此如果它们在表单中是 edited/changed,则不会复制字段。明白了吗?为了能够做到这一点,我们需要更多 javascript-code,这可能也是一种非常有效的方法,也许更简单:触发 link_to_add_association link 并在 cocoon:after-insert如果有的话,我们可以预填从 to-be-cloned 项复制的字段。但是,如前所述,那将是一个纯粹的 javascript 解决方案。

为了接近您最初的建议,您的视图应该是这样的(我没有复制整个视图)

<!-- views/mantenimiento_setups/_form.html.erb --> 

<%= f.fields_for :actuation_setups do |act_setup_builder| -%>
  <%= render 'actuation_setup_fields', f: act_setup_builder, parent_f: f %>
<% end -%>

然后在你的嵌套表格中你可以写:

<!-- views/mantenimiento_setups/_actuation_setup_fields.html.erb -->
<div class='row fields'>
  <div class="col-md-3 actuation-type-div-selector">
        
  <div class="col-md-1">
    <label class="control-label invisible">...</label><br/>
    <%= link_to_remove_fields "Remove", f%>
  </div>

  <% if local_assigns.has_key?(:parent_f) %>
    <div class="col-md-1">
    
      <%= link_to_add_association 'Clone', parent_f, :actuation_setups, data: {"association-insertion-node" => ".mantenimiento-setup-element", "association-insertion-method" => "append"}, wrap_object: Proc.new {|d| d = act_setup_builder.object.dup; d}, class: "btn btn-info btn-sm" %>
    </div>
  <% end %>
</div>

(我的 erb 有点生疏,我总是写 haml 或 slim,因为我发现它们更易读,更少 typing-work,所以可能会有一些错别字)。

简而言之:对于每个现有的 :actuation_setup,我们传递 parent_f 参数(parent-form-object),并在嵌套的 child我们检查是否给出了这个参数,如果是,我们知道它是一个现有的 child,所以我们添加 clone-link,并使用 parent-form-object 作为能够添加新的嵌套 child 作为 existing/given 嵌套 child.

的副本