Save 36% for Black Friday! Learn more

New Discussion

Notifications

You’re not receiving notifications from this thread.

How can I add multiple dynmic nested fields in the same form?

0
Rails

I have a registration form that allows tournament directors to select which fields they will request when participants register for a tournament. I followed a video to add dynamic nested form fields into a form using stimulus JS and it works great.

I am trying to add a second group of fields in another section fo the form. the form is broken into section, basic info, contact info, competition info, etc and I would like to have the ability to add custom fields to each section.

In the basic section it works great. I can add and remove custom fields, but when I added it to the contact section, even with change nested-form to nested-contacts, it just puls in the fields I create in the basic section. I can add and remvoe from either section but it just shows them all in both sections.

Here is my form as it is now. I still have to add the other sections but was trying to get basic and contact custom fields working before adding the rest of the form:

<h4>Athlete Information</h4>
<%= form_with(model: @event, class: "shadow p-3 mb-3 rounded text-dark", local: true) do |f| %>
  <%= f.hidden_field :athlete_info_complete, value: 1 %>
  <%= f.hidden_field :next, value: 6 %>
  <div class="row club_container">
    <div class="col-12">
      <legend>
        Check all the boxes next to the information you would like to
        request from your tournament participants.  Each area will have an option 
        to add custom fields.
      </legend>
      <br><br>
      <h4>Basic Information</h4>
      <div class="form-group row">
        <div class="col-md-9 col-sm-12">
          <label class="main">First Name
            <%= f.check_box :first_name %>
            <span class="w3docs"></span>
          </label>
          <label class="main">Last Name
            <%= f.check_box :last_name %>
            <span class="w3docs"></span>
          </label>
          <label class="main">Date of birth
            <%= f.check_box :dob %>
            <span class="w3docs"></span>
          </label>
        </div>
      </div>
      <h4>Custom Fields</h4>
      <small>
        Enter the name of your custom field you plan to offer.
      </small>
      <br><br>

      <div data-controller="nested-form">
        <template data-target="nested-form.template">
          <%= f.fields_for :fields, Field.new, child_index: 'NEW_RECORD' do |field| %>
            <%= render 'events/forms/custom_fields_basic', f: field %>
          <% end %>
        </template>

        <%= f.fields_for :fields do |field| %>
          <%= render 'events/forms/custom_fields_basic', f: field %>
        <% end %>
        <div class="mb-3" data-target="nested-form.links">
          <%= link_to 'Add Custom Field', "#", class: "btn btn-outline-dark", data: { action: "click->nested-form#add_association" } %>
        </div>
      </div>

      <h4>Contact Information</h4>
      <div class="form-group row">
        <div class="col-md-9 col-sm-12">
          <label class="main">Address 1
            <%= f.check_box :address1 %>
            <span class="w3docs"></span>
          </label>
          <label class="main">Address 2
            <%= f.check_box :address2 %>
            <span class="w3docs"></span>
          </label>
          <label class="main">City
            <%= f.check_box :city %>
            <span class="w3docs"></span>
          </label>
        </div>
      </div>

      <div data-controller="nested-contacts">
        <template data-target="nested-contacts.template">
          <%= f.fields_for :fields, Field.new, child_index: 'NEW_RECORD' do |field| %>
            <%= render 'events/forms/custom_fields_contact', f: field %>
          <% end %>
        </template>

        <%= f.fields_for :fields do |field| %>
          <%= render 'events/forms/custom_fields_contact', f: field %>
        <% end %>
        <div class="mb-3" data-target="nested-contacts.links">
          <%= link_to 'Add Custom Field', "#", class: "btn btn-outline-dark", data: { action: "click->nested-contacts#add_association" } %>
        </div>
      </div>

      <div class="form-group row">
        <div class="col-md-9 col-sm-12"></div>
        <div class="col-md-3 col-sm-12">
          <button id="button_next" class="profile_btn align-middle" style="width:180px;">Finalize <span style="margin-top: 5px; font-size: 18px;"><i class="fas fa-long-arrow-alt-right"></i></span></button>
        </div>
      </div>
    </div>
  </div>
<% end %>

Here is the _custom_fields_basic.html.erb

<%= content_tag :div, class: 'nested-fields', data: { new_record: f.object.new_record? }  do %>
  <div class="form-group row">
    <div class="col-md-3 col-sm-12 col-form-label">
      <%= f.label :field_name %>
    </div>
    <div class="col-md-9 col-sm-12">
      <%= f.text_field :name, class: 'form-control' %>
      <small><%= link_to 'Remove', '#', data: { action: 'click->nested-form#remove_association' } %></small>
    </div>
  </div>
  <%= f.hidden_field :field_type, value: 'basic' %>
  <%= f.hidden_field :_destroy %>
<% end %>

This is the custom_fields_contact.html.erb file:

<%= content_tag :div, class: 'nested-contacts', data: { new_record: f.object.new_record? }  do %>
  <div class="form-group row">
    <div class="col-md-3 col-sm-12 col-form-label">
      <%= f.label :field_name %>
    </div>
    <div class="col-md-9 col-sm-12">
      <%= f.text_field :name, class: 'form-control' %>
      <small><%= link_to 'Remove', '#', data: { action: 'click->nested-contacts#remove_association' } %></small>
    </div>
  </div>
  <%= f.hidden_field :field_type, value: 'contact' %>
  <%= f.hidden_field :_destroy %>
<% end %>

Here is the nexted_form_controller.js

import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "links", "template" ]

  connect() {

  }

  add_association(event) {
    event.preventDefault()

    var content = this.templateTarget.innerHTML.replace(/NEW_RECORD/g, new Date().getTime())
    this.linksTarget.insertAdjacentHTML('beforebegin', content)
  }

  remove_association(event) {
    event.preventDefault()

    let wrapper = event.target.closest(".nested-fields")
    if (wrapper.dataset.newRecord == "true") {
      wrapper.remove()
    } else {
      wrapper.querySelector("input[name*='_destroy']").value = 1
      wrapper.style.display = 'none'
    } 
  }
}

And the nested_contacts_controller.js:

import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "links", "template" ]

  connect() {

  }

  add_association(event) {
    event.preventDefault()

    var content = this.templateTarget.innerHTML.replace(/NEW_RECORD/g, new Date().getTime())
    this.linksTarget.insertAdjacentHTML('beforebegin', content)
  }

  remove_association(event) {
    event.preventDefault()

    let wrapper = event.target.closest(".nested-contacts")
    if (wrapper.dataset.newRecord == "true") {
      wrapper.remove()
    } else {
      wrapper.querySelector("input[name*='_destroy']").value = 1
      wrapper.style.display = 'none'
    } 
  }
}

If there is way to do it with a single controller that would be great, but I'm ok with having separate controllers for each section if necessary.

Thanks

Join the discussion
Create an account Log in