-
Notifications
You must be signed in to change notification settings - Fork 1
Nested Fields
Dylan Fisher edited this page Apr 6, 2022
·
21 revisions
# rails g forest:block AccordionBlock
class AccordionBlock < BaseBlock
has_many :accordion_block_items, -> { order(:position) }, dependent: :destroy, inverse_of: :accordion_block
accepts_nested_attributes_for :accordion_block_items, reject_if: :all_blank, allow_destroy: true
validates_associated :accordion_block_items
def self.permitted_params
[
accordion_block_items_attributes:
[:_destroy, :id, :position, :title, :text]
]
end
end# rails g model AccordionBlockItem accordion_block:references position:integer title:string text:text
class AccordionBlockItem < ApplicationRecord
belongs_to :accordion_block, inverse_of: :accordion_block_items, touch: true
end<%# app/views/blocks/accordion_block/_edit.html.erb %>
<div class="row small-gutters">
<div class="col">
<div class="sortable-field-set">
<% if f.object.errors[:slideshow_block_items].present? && f.object.slideshow_block_items.blank? %>
<div class="col-12 bg-danger text-white mb-3 p-3 rounded">
Slideshow block items <%= f.object.errors[:slideshow_block_items].to_sentence %>
</div>
<% end %>
<%= f.simple_fields_for :slideshow_block_items do |record| %>
<%= render 'blocks/slideshow_block/slideshow_block_item_fields', f: record %>
<% end %>
<%= link_to_add_association (bootstrap_icon('plus-lg', embedded: true) + ' Add item'),
f,
:slideshow_block_items,
partial: 'blocks/slideshow_block/slideshow_block_item_fields',
class: 'btn btn-secondary mb-3',
data: {
association_insertion_node: 'this',
association_insertion_method: 'before'
} %>
</div>
</div>
</div><%# /app/views/blocks/accordion_block/_accordion_block_item_fields.html.erb %>
<div class="nested-fields sortable-field">
<div class="card">
<h3 class="card-header sortable-field-set__handle h5 d-flex align-items-baseline">
<div class="nested-fields__header-label">
<%= f.object.try(:title).presence || 'Slideshow item' %>
</div>
<%= link_to_remove_association (bootstrap_icon('x-lg', embedded: true) + ' Remove item'), f, class: 'nested-fields__remove-fields-button btn btn-outline-secondary ml-auto' %>
</h3>
<div class="card-body">
<div class="row small-gutters">
<div class="col">
<%= f.association :media_item, as: :image %>
</div>
</div>
</div>
</div>
<div class="sortable-field-set__position">
<%= f.input :position, as: :hidden %>
</div>
</div>For simpler nested field structures, use the following pattern to add inline nested fields. This example also automatically instantiates the nested field field by calling the build method on it.
<%# /app/views/blocks/button_block/_edit.html.erb %>
<div class="row small-gutters">
<div class="col">
<% if f.object.errors[:button_block_items].present? && f.object.button_block_items.blank? %>
<div class="bg-danger text-white mb-3 p-3 rounded">
button block items <%= f.object.errors[:button_block_items].to_sentence %>
</div>
<% end %>
<div class="row small-gutters button-block-cocoon-node sortable-field-set">
<%= f.simple_fields_for :button_block_items, (f.object.button_block_items.build if f.object.button_block_items.blank?) do |record| %>
<%= render 'blocks/button_block/button_block_item_fields', f: record %>
<% end %>
</div>
<%= link_to_add_association (bootstrap_icon('plus-lg', embedded: true) + ' Add button'),
f,
:button_block_items,
partial: 'blocks/button_block/button_block_item_fields',
class: 'btn btn-secondary mb-3',
data: {
association_insertion_traversal: 'prev',
association_insertion_node: '.button-block-cocoon-node',
association_insertion_method: 'append'
} %>
</div>
</div><%# /app/views/blocks/button_block/_button_block_item_fields.html.erb %>
<div class="col-md-4 nested-fields sortable-field">
<div class="card">
<h3 class="card-header sortable-field-set__handle h5 d-flex align-items-baseline">
<div class="nested-fields__header-label">
<%= f.object.try(:label).presence || 'Button' %>
</div>
<%= link_to_remove_association (bootstrap_icon('x-lg', embedded: true)), f, class: 'nested-fields__remove-fields-button btn btn-outline-secondary ml-auto', title: 'Remove this item' %>
</h3>
<div class="card-body">
<div class="row small-gutters">
<div class="col">
<%= f.input :title %>
</div>
</div>
</div>
</div>
<div class="sortable-field-set__position">
<%= f.input :position, as: :hidden %>
</div>
</div>