使用 Cocoon 在 link_to_add_association 点击​​时自动添加嵌套的子部分

Posted

技术标签:

【中文标题】使用 Cocoon 在 link_to_add_association 点击​​时自动添加嵌套的子部分【英文标题】:Automatically adding nested child partials on link_to_add_association click using Cocoon 【发布时间】:2020-12-08 03:41:53 【问题描述】:

我有一个包含 4 个嵌套级别的表单,我用它来动态添加商品、发货和计算成本。我已将表单设置为可以通过单击按钮添加/删除所需的所有内容。页面初始渲染的一切都符合预期。

但是,当我添加中级嵌套的新实例(SubQuote 和 QuoteShipment)时,它只会呈现自身(例如 SubQuote),而不是在其部分(QuoteShipment)中引用的任何部分。我想要一个按钮来自动渲染它下面的所有嵌套部分。

我的相关模型是结构化的:

class Quote < ApplicationRecord
  has_many :sub_quotes, dependent: :destroy, inverse_of: :quote
  accepts_nested_attributes_for :sub_quotes, reject_if: :all_blank
end


class SubQuote < ApplicationRecord
    belongs_to :quote
    has_many :quote_shipments, dependent: :destroy, inverse_of: :sub_quote
    accepts_nested_attributes_for :quote_shipments, reject_if: :all_blank
end

class QuoteShipment < ApplicationRecord
    has_many :quote_items, dependent: :destroy, inverse_of: :quote_shipment, class_name: "::QuoteItem"
    belongs_to :sub_quote
    accepts_nested_attributes_for :quote_items, reject_if: :all_blank
end

Class QuoteItem < ApplicationRecord
    belongs_to :quote_shipment
end

在页面加载时呈现 QuoteShipment 部分的 SubQuote 类的部分,而不是在 link_to_add_association 点击​​时。

<div class="col nested-sub_quote-fields" id="sub_quote_identifier">

  <div class="row">
    <%= link_to_remove_association button_tag('remove sub_quote', type: "button", class: "btn btn-sm btn-outline red-btn add-quote"), f ,  wrapper_class: "nested-sub_quote-fields" %>
  </div>

  <div class="row" class="">
  
    <div id="sub_quote" class="col mt-0 mt-md-4 mb-4 p-0">
      <div class="col ">
        <div class="col-lg col-sm-12 col-md-12">
          <%= f.fields_for :quote_shipments do |shipment| %>
            <%= render partial: "quotes/quote_shipment_fields", :locals =>  :f => shipment  %>
          <% end %>
          <div class='links'>
            <%= link_to_add_association button_tag('Add Shipment', type: "button", class: "btn btn-sm btn-outline btn-primary add-quote"), f, :quote_shipments %>
          </div>
        </div>
      </div>
    </div>
    
    <div class="col-lg-5 col-sm-12 col-md-12">
      <%= render partial: "quotes/cost", locals:  f: f  %>
    </div>
    
  </div>
</div>

以上述关系为例:

如果我单击 SubQuote 类的 link_to_add_association,我希望它呈现 SubQuote 部分,以及 QuoteShipment 部分的 1 个实例和 QuoteItem 部分的 1 个实例。

如果我单击了 QuoteShipment 部分的 link_to_add_association,我希望它使用嵌套在新 QuoteShipment 部分下方的 QuoteItem 部分的 1 个实例来呈现。

我试过了:

在 Jquery 中使用“insert-after”方法,但部分需要 fields_for 变量,我认为该变量无法访问 在控制器上实例化更多实例 大量谷歌搜索。要么没有人问这个问题,要么我搜索的方式错误

我认为在更糟糕的情况下,我可以为我拥有的每个不同级别的 link_to_add_association 按钮生成不同的部分,但这似乎非常多余

【问题讨论】:

【参考方案1】:

link_to_add_association 具有:wrap_object 选项(检查documentation),允许在渲染部分之前添加额外的初始化。

所以在你的情况下,你可以这样:

= link_to_add_association button_tag('Add Shipment', type: "button", class: "btn btn-sm btn-outline btn-primary add-quote"), 
                          f, :quote_shipments, 
                          wrap_object: Proc.new|shipment| shipment.quote_items.build; shipment 

wrap_object 部分内,您可以进行任何您想要的初始化,只要您返回要呈现的嵌套项(在本例中为shipment)。 在这个例子中,我们将 buildQuoteItem 进行渲染。

对于SubQuote,你可以做类似的事情。例如。像

wrap_object: Proc.new|sub_quote| shipment = sub_quote.quote_shipments.build; shipment.quote_items.build; sub_quote            

【讨论】:

这正是我所需要的!非常感谢!另外,感谢您构建如此令人头疼的节省 Gem

以上是关于使用 Cocoon 在 link_to_add_association 点击​​时自动添加嵌套的子部分的主要内容,如果未能解决你的问题,请参考以下文章

使用 simple_form 和 cocoon 时无法让 select2 工作

Cocoon 自动完成模态填充动态字段两次

使用 Cocoon 在 link_to_add_association 点击​​时自动添加嵌套的子部分

Rails cocoon嵌套字段,在编辑表单上呈现每个字段旁边的现有图像

在 Ruby on Rails 4.2 中使用 Cocoon gem 嵌套表单

如何将复制按钮集成到使用 cocoon gem 创建的表单中