stimulus-rails-nested-form
stimulus-rails-nested-form copied to clipboard
Having a double nested form?
Hi! I'm new to Stimulus, and I have a little issue trying to use the nested form component.
I have a survey model with many questions, and my question model has many answers. I want to be able to create a survey, and add both questions & answers on the same view.
It works okay with a level 1 nesting (for the questions) but, I'm have a hard time adding the answer logic to it. When I'm adding an answer, it duplicates the creation of a question, I know it has to come from the way the target are set-up, but I can't find a way to have both actions being separated (a button to create a question, and one to create an answer).
I followed up this tutorial to do so, but he does not seems to encounter this issue.
Here is my initial _form :
`<%= simple_form_for ([@survey]), data: { controller: 'nested-form', nested_form_wrapper_selector_value: '.nested-form-wrapper' } do |f| %>
<template data-nested-form-target="template">
<%= f.simple_fields_for :questions, Question.new, child_index: 'NEW_RECORD' do |question| %>
<%= render "question_fields", f: question %>
<% end %>
</template>
<%= f.fields_for :questions do |question| %>
<%= render "question_fields", f: question %>
<% end %>
<!-- Inserted elements will be injected before that target. -->
<div data-nested-form-target="target">
<%= f.button :submit, "Add question", data: {action:"nested-form#add"} %>
</div>
<%= f.submit 'Create survey' %>
<% end %>`
My _question partial :
<div class="nested-form-wrapper" data-new-record="<%= f.object.new_record? %>">
<%= f.input :body, label: "Question" %>
<%= f.button :submit, "Delete question", data: {action:"nested-form#remove"} %>
<%= f.hidden_field :_destroy %>
</div>
<template data-nested-form-target="template">
<%= f.simple_fields_for :answers, Answer.new, child_index: 'NEW_RECORD' do |answer| %>
<%= render "answer_fields", f: answer %>
<% end %>
</template>
<%= f.fields_for :answers do |answer| %>
<%= render "answer_fields", f: answer %>
<% end %>
<!-- Inserted elements will be injected before that target. -->
<div data-nested-form-target="target"></div>
<%= f.button :submit, "Add answer", data: {action:"nested-form#add"} %>
And my _answer partial :
<div class="nested-form-wrapper" data-new-record="<%= f.object.new_record? %>">
<%= f.input :body, label: "Answer" %>
<%= f.button :submit, "Delete answer", data: {action:"nested-form#remove"} %>
<%= f.hidden_field :_destroy %>
</div>
If anybody had this issue before, it would love to know how you dealt with it, thanks!
@kobaltz's tutorial that you linked to has a source download and if you inspect it, you'll see he is not using this project. Instead, he simply defined his own stimulus controller for the same purpose:
// app/assets/javascripts/controllers/nested_form_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
static targets = ["add_item", "template"]
add_association(event) {
event.preventDefault()
var content = this.templateTarget.innerHTML.replace(/TEMPLATE_RECORD/g, new Date().valueOf())
this.add_itemTarget.insertAdjacentHTML('beforebegin', content)
}
remove_association(event) {
event.preventDefault()
let item = event.target.closest(".nested-fields")
item.querySelector("input[name*='_destroy']").value = 1
item.style.display = 'none'
}
}
As a result, I wouldn't say it's safe to assume this component will work the same way, re: multi-nesting