Rails nested form (new gem with Stimulus)

hungle00

hungle00

Posted on June 18, 2023

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


 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:


 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 %>


Enter fullscreen mode Exit fullscreen mode

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>


Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
hungle00
hungle00

Posted on June 18, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related