With dynamic nested forms, you can create forms that automatically calculate fields based on the information that has been entered into previous fields. If you’re building a form for your online store, for example, you might want to create a product listing form with several different fields: name, category and price. If the user selects “blue jeans” as their category and then enters $50 as their price, then the form will automatically calculate all of the necessary information—including tax—and display it in an easy-to-read format.
Dynamic nested forms are also an excellent way to reduce the amount of code needed to create your form. It’s a lot easier than building out each section manually, and it’s also more secure and more scalable than using a single form.
In this post, we will discuss how to create dynamic nested forms in Ruby on Rails using Cocoon gem. We will use two models, product and FAQ. The product can have multiple FAQs, which we will add manually while creating it.
1 gem "cocoon"
1 yarn add @nathanvda/cocoon
Let’s do some database stuff.
1 2 3 rails g scaffold Product name price:integer rails g model Faq question answer product:belongs_to rails db:migrate
1 2 3 4 5 6 # app/models/product.rb class Product < ApplicationRecord has_many :faqs, inverse_of: :product accepts_nested_attributes_for :faqs, reject_if: :all_blank, allow_destroy: true end
1 2 3 4 5 6 # app/controllers/products_controller.rb def product_params params.require(:product).permit(:name, :price, faqs_attributes: [:id, :question, :answer, :_destroy]) end
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # app/views/products/_form.html.erb <%= semantic_form_for @product do |f| %> <% f.inputs do %> <%= f.input :name %> <%= f.input :price %> <h3>FAQs</h3> <div id='faqs'> <%= f.semantic_fields_for :faqs do |faq| %> <%= render 'faq_fields', :f => faq %> <% end %> <div class='links'> <%= link_to_add_association 'add faq', f, :faqs %> </div> </div> <% f.buttons do %> <%= f.submit 'Save' %> <% end %> <% end %> <% end %>
Create a new partial
1 2 3 4 5 6 7 8 9 # app/views/products/_faq_fields.html.erb <div class='nested-fields'> <%= f.inputs do %> <%= f.input :question %> <%= f.input :answer %> <%= link_to_remove_association "remove faq", f %> <% end %> </div>
You’ll also need to make certain that jQuery is properly added to your project.