使用 Cocoon 在 link_to_add_association 单击时自动添加嵌套子部分
Automatically adding nested child partials on link_to_add_association click using Cocoon
我有一个包含 4 个嵌套级别的表单,我用它来动态添加项目、发货和计算成本。我已将表单设置为 add/remove 我需要的一切,只需单击按钮即可。关于页面初始呈现的一切都符合预期。
但是,当我添加新的中级嵌套实例(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
部分用于 SubQuote class,它在页面加载时呈现 QuoteShipment 部分,但在 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 class 单击 link_to_add_association,我希望它呈现 SubQuote 部分,以及 QuoteShipment 部分的 1 个实例,并且1 个 QuoteItem 部分实例。
如果我单击了 QuoteShipment 部分的 link_to_add_association,我希望它使用嵌套在新 QuoteShipment 部分下方的 QuoteItem 部分的 1 个实例进行呈现。
我试过:
- 使用 Jquery 中的“insert-after”方法,但是部分需要 fields_for 变量,我认为这是不可访问的
- 在控制器上实例化更多实例
- 大量谷歌搜索。要么没有人问这个问题,要么我搜索的方式不对
我认为在更糟糕的情况下,我可以为每个不同级别的 link_to_add_association 按钮生成不同的部分,但这似乎非常多余
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
局部你可以做任何你想要的初始化,只要你 return 要渲染的嵌套项目(在这个例子中 shipment
)。
在这个例子中我们 build
a QuoteItem
所以它会被渲染。
对于 SubQuote
你可以做类似的事情。例如。像
wrap_object: Proc.new{|sub_quote| shipment = sub_quote.quote_shipments.build; shipment.quote_items.build; sub_quote }
我有一个包含 4 个嵌套级别的表单,我用它来动态添加项目、发货和计算成本。我已将表单设置为 add/remove 我需要的一切,只需单击按钮即可。关于页面初始呈现的一切都符合预期。
但是,当我添加新的中级嵌套实例(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
部分用于 SubQuote class,它在页面加载时呈现 QuoteShipment 部分,但在 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 class 单击 link_to_add_association,我希望它呈现 SubQuote 部分,以及 QuoteShipment 部分的 1 个实例,并且1 个 QuoteItem 部分实例。
如果我单击了 QuoteShipment 部分的 link_to_add_association,我希望它使用嵌套在新 QuoteShipment 部分下方的 QuoteItem 部分的 1 个实例进行呈现。
我试过:
- 使用 Jquery 中的“insert-after”方法,但是部分需要 fields_for 变量,我认为这是不可访问的
- 在控制器上实例化更多实例
- 大量谷歌搜索。要么没有人问这个问题,要么我搜索的方式不对
我认为在更糟糕的情况下,我可以为每个不同级别的 link_to_add_association 按钮生成不同的部分,但这似乎非常多余
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
局部你可以做任何你想要的初始化,只要你 return 要渲染的嵌套项目(在这个例子中 shipment
)。
在这个例子中我们 build
a QuoteItem
所以它会被渲染。
对于 SubQuote
你可以做类似的事情。例如。像
wrap_object: Proc.new{|sub_quote| shipment = sub_quote.quote_shipments.build; shipment.quote_items.build; sub_quote }