cocoonからstimulusに置き換えました
2025/02/22 | Ruby on Rails
railsのcocoonは親フォームで子要素を作成できる便利なgemでしたのでよく使っていましたが、jquery依存でしたのでstimulusに置き換えてみました。stimulusの設定は終わっている前提です。hamlとsimple_formを使用しています。
rails 7.0.8.7
ruby 3.2.6
model/post
class Post < ApplicationRecord
accepts_nested_attributes_for :post_tags, reject_if: :all_blank, allow_destroy: true
end
app/javascript/nested_controller.js
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["container", "template"];
add(event) {
event.preventDefault();
const template = this.templateTarget.innerHTML.replace(/NEW_RECORD/g, new Date().getTime());
this.containerTarget.insertAdjacentHTML("beforeend", template);
}
remove(event) {
event.preventDefault();
const wrapper = event.target.closest(".nested-fields");
if (wrapper) {
const destroyField = wrapper.querySelector(".destroy-field");
if (destroyField) {
destroyField.value = "1";
wrapper.style.display = "none";
} else {
wrapper.remove();
}
}
}
}
app/views/posts/_form.html.haml
#post_tags{ data: { controller: "nested-form" } }
.nested-fields-container{ data: { nested_form_target: "container" } }
= f.simple_fields_for :post_tags do |post_tag|
= render 'post_tag_fields', f: post_tag
.links
= link_to 追加, "#", data: { action: "nested-form#add" }, class: "btn btn-primary"
/ フィールドのテンプレート
= content_tag :template, id: "post_tag_template", data: { nested_form_target: "template" } do
= f.simple_fields_for :post_tags, PostTags.new, child_index: "NEW_RECORD" do |post_tag|
= render 'post_tag_fields', f: post_tag
app/views/posts/_post_tag_fields.html.haml
.nested-fields
= f.hidden_field :_destroy, class: "destroy-field", value: "0"
.row
.col-lg-10
= f.input :post_tag_text
.col-lg-2
= link_to 削除, "#", data: { action: "nested-form#remove" }, class: "btn btn-danger"