Search code examples
ruby-on-railsnested-formscocoon-gembootstrap-tabs

Rails Nested Fields with Bootstrap Tabs


Trying to create a nested form in rails, but have it collapsible using bootstrap tabs.
I currently have the following:

_form.html.rb

  <%= f.fields_for :register_members do |rm| %>

    <%= render 'register_member_fields', f: rm %>
  <% end %>

  <div class="links">
  <%= link_to_add_association "Add Registration", f, :register_members, class: "btn btn-success btn-sm text-white" %>
  </div>

_register_member_fields.html.erb

<div class="nested-fields">
  <div class="panel panel-default fields">

    <div class="panel-heading" role="tab" id="heading<%= f.index.to_s %>">
      <h4 class="panel-title">
        <a data-toggle="collapse" href="#tabCollapse<%= f.index.to_s %>" aria-expanded="true" aria-controls="tabCollapse<%= f.index.to_s %>">
            Registration
            <span class="panel-icon"></span>
        </a>
      </h4>
    </div><!-- End .panel-heading -->

    <div id="tabCollapse<%= f.index.to_s %>" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="heading<%= f.index.to_s %>">
      <div class="panel-body">
        <div class="field">
            <%= f.label "Name", class: "input-desc" %>
            <%= f.text_field :name, class: "form-control" %>
        </div>
        <div class="field">
            <%= f.label :email, class: "input-desc" %>
            <%= f.email_field :email, class: "form-control" %>
        </div>
        <div class="field">
            <%= f.hidden_field :_destroy %>
            <%= link_to_remove_association("Remove Registration", f) %>
        </div>
      </div><!-- End .panel-body -->
    </div><!-- End .panel-collapse -->  

  </div><!-- End .panel -->
</div>  

Obviously with how nested fields work using the gem cocoon this will create a new _register_member_field using the same id for the collapse. Which means clicking on any of the panel headings will only collapse and open one of the nested forms.
Any suggestions on how I can get this to work properly?


Solution

  • Ok, so from what I can tell in rails & JQUERY - if you are sticking arbitrary id's in to the situation without the need for a DSL or model that back it's up - that's code smell (when you do a ton of work for a hack, that normally other programmers would just use another method which does the same thing in a universal way).

    I think what you are doing is essentially trying to use Rails code to write HTML code to jam ID#'s in for the JQUERY code to use.

    Since you already have cocoon using JQUERY, why not just use better JQUERY selectors (google '.selector') to target the CSS/HTML element you want ... if you're aware of the DOM, then you're doing good in this respect. I would suggest targeting '.child'. There's also some tricks for doing themes to this...Link. This relieves the need for unique values since you are just using what's already there.

    The beautiful part of this is cocoon's pattern by default is already to target the "parent" of nested-fields. Which gives you an example of how this will work - especially if you read the cocoon documentation about callbacks.

    Basically, you need to put the accordion equivalent of nested-fields (pick any ONE name & use it for all the fields - example: 'accordion-fields') around each specific collapse & then point your JQUERY for accordion for the click to target the parent of 'accordion-fields'.

    Bonus, here's an example of dynamically targeting accordion fields - http://demos.jquerymobile.com/1.4.3/collapsible-dynamic/#&ui-state=dialog

    I got it going once a few months ago - but I will need some time to anatomize it - just posting this here because this is the technique & it's faster than actually writing your whole code for you. Let me know if you hit any snags implementing the parent/child strategy with JQUERY.