Rails nested form (new gem with Stimulus)

Share this post:


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.

Same as Cocoon, but using StimulusJS

Handle dynamic nested forms, same as Cocoon, but using StimulusJS

Installation

Install the gem and add to the application’s Gemfile by executing:

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.



Source link