Nested forms are forms that handle nested models and attributes in one form; e.g. a project with its tasks or an invoice with its line items.
Before Rails 6, Cocoon is a good choice for creating dynamic nested forms. But Cocoon needs jQuery to work well, it's a very old library on modern-day frontend frameworks.
When Stimulus is came out, Rails devs is suggested to use Stimulus as Javascript library in their projects. So, I created a gem for handling dynamic nested forms with Stimulus JS.
hungle00 / rondo_form
Same as Cocoon, but using StimulusJS https://rubygems.org/gems/rondo_form
RondoForm
Handle dynamic nested forms, same as Cocoon, but using StimulusJS
Installation
Install the gem and add to the application's Gemfile by executing:
$ bundle add rondo_form
Or inside the Gemfile add the following
$ gem 'rondo_form', '~> 0.2.6'
Run the installation task:
$ rails g rondo_form:install
Usage
For example, you have Project
model, which has has_many
relationship with Task
model:
rails g scaffold Project name:string description:string
rails g model Task description:string done:boolean project:belongs_to
You need to add accepts_nested_attributes_for
to Project
model:
class Project < ApplicationRecord
has_many :tasks, dependent: :destroy
accepts_nested_attributes_for :tasks, reject_if: :all_blank, allow_destroy: true
end
Sample with SimpleForm
The RondoForm gem adds two helper functions: link_to_add_association
and link_to_remove_association
.
The example below illustrates the way to use it.
In your projects/_form
partial:
<%= simple_form_for(@project) do |f| %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.input :description %>
</div
…Rondo Form is easy to use, it has the same tag helpers name as cocoon: link_to_add_association
, link_to_remove_association
.
This gem does not need JS dependencies to work with, when you run under command, it will generate nested_rondo_controller.js
in your app/javascript/controllers/
folder:
rails g rondo_form:install
And auto import this controller into index.js.
js
import NestedRondoController from "./nested_rondo_controller"
application.register("nested-rondo", NestedRondoController)
You must add data-controller="nested-rondo"
to an element, that wraps fields_for
and link_to_add_association
helper.
For example, we have Project model, which has has_many
relationship with Task model.
In your projects/_form
partial:
erb
<%= simple_form_for(@project) do |f| %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.input :description %>
</div>
<h3>Tasks</h3>
<div data-controller="nested-rondo">
<%= f.simple_fields_for :tasks do |task| %>
<%= render "task_fields", f: task %>
<% end %>
<div class="links">
<%= link_to_add_association "Add Task", f, :tasks %>
</div>
</div>
<%= f.button :submit %>
<% end %>
In your _task_fields
partial:
erb
<div class="nested-fields">
<%= f.input :description %>
<%= f.input :done, as: :boolean %>
<%= link_to_remove_association "Remove Task", f %>
</div>
This sample I built with SimpleForm gem, but the idea is the same with Rails standard form.
Top comments (1)
Excelent.