DEV Community

hungle00
hungle00

Posted on

Rails nested form (new gem with Stimulus)

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.

GitHub logo hungle00 / rondo_form

Same as Cocoon, but using StimulusJS

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.1'

Run the installation task:

$ rails g rondo_form:install

Usage

For example, we 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

Sample with SimpleForm

In your projects/_form partial:

<%= simple_form_for(@project) do |f| %>
  <div class="form-inputs">
    <%= f.input :name %>
    <%= f.input :description %>
  </div>

  <h3 class="text-xl mt-4">Tasks</h3>
  <div class="my-2" data-controller="nested-rondo">
    <%= f.simple_fields_for :tasks do |task| %>
      <%= render "task_fields", f: task %>
    <%
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

And auto import this controller into index.js.

import NestedRondoController from "./nested_rondo_controller"
application.register("nested-rondo", NestedRondoController)
Enter fullscreen mode Exit fullscreen mode

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:

<%= 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 %>
Enter fullscreen mode Exit fullscreen mode

In your _task_fields partial:

<div class="nested-fields">
  <%= f.input :description %>
  <%= f.input :done, as: :boolean %>
  <%= link_to_remove_association "Remove Task", f %>
</div>
Enter fullscreen mode Exit fullscreen mode

This sample I built with SimpleForm gem, but the idea is the same with Rails standard form.

Top comments (1)

Collapse
 
marcelonmoraes profile image
Marcelo Moraes

Excelent.