Skip to content
This repository

Double nested forms aren't rendered #91

Closed
dnagir opened this Issue September 24, 2012 · 9 comments

3 participants

Dmytrii Nagirniak Nathan Van der Auwera htowens
Dmytrii Nagirniak

It appears that it is not possible to use this gem ATM with double nested forms.

When we want to show fields for another association rendered via fields_for/simple_fields_for those are just ignored.

This restrictions only allows to use the 'flat' dynamic listes without nested models within the lists.

Pretty important for me ATM and wonder if it would be possible to fix it somehow.

Nathan Van der Auwera
Owner

Hmmmm I have used it successfully with double, and more, nested forms. So it definitely is possible. Could you show me your form-code?

Dmytrii Nagirniak
= simple_form_for @company_invitation, html: {class: 'form-horizontal'} do |i|
  = i.simple_fields_for :company do |c|
    = c.input :name
    %h2 Additional users
    %table.table.table-striped.table-bordered
      %thead
        %tr
          %th= Participation.human_attribute_name(:category)
          %th= User.human_attribute_name(:email)
          %th= User.human_attribute_name(:first_name)
          %th= User.human_attribute_name(:last_name)
          %th= User.human_attribute_name(:password)
          %th
            = link_to_add_association '+', i, :participations , class: 'btn btn-success btn-small', 'data-association-insertion-node' => '#participations', 'data-association-insertion-method' => 'append'
      %tbody#participations
        = c.simple_fields_for :participations do |participations_form|
          = render 'additional_participation_fields', f: participations_form

and the partial:

%tr.nested-fields{class: f.object.errors.any? ? 'error' : '' }
  %td
    = f.input :category, collection: Participation.category_hash.invert, include_blank: false, wrapper: :embeded
  = f.simple_fields_for :user do |u|
    %td
      = u.input :email, wrapper: :embeded
    %td
      = u.input :first_name, wrapper: :embeded
    %td
      = u.input :last_name, wrapper: :embeded
  %td
    = link_to_remove_association "x", f, class: 'btn btn-danger btn-small'

The workaround is to "flatten" the fields (delegate the assignment and validations):

%tr.nested-fields{class: f.object.errors.any? ? 'error' : '' }
  %td
    = f.input :category, collection: Participation.category_hash.invert, include_blank: false, wrapper: :embeded
  %td
    = f.input :user_email, wrapper: :embeded
  %td
    = f.input :user_first_name, wrapper: :embeded
  %td
    = f.input :user_last_name, wrapper: :embeded
  %td
    = link_to_remove_association "x", f, class: 'btn btn-danger btn-small'

The models look like:

class CompanyInvitation < ActiveRecord::Base
  belongs_to :company, autosave: true
end

class Company < ActiveRecord::Base
  has_many :participations, :dependent => :destroy, :autosave => true
end

class Participation < ActiveRecord::Base
  belongs_to :company
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many  :participations, :dependent => :destroy
end
Nathan Van der Auwera
Owner

At first sight this looks ok, I will try this out this evening.

To be honest: imho what you are doing is not even related to cocoon, but it should work.

Dmytrii Nagirniak
Nathan Van der Auwera
Owner
htowens

+1

I'm having the same issue - I believe it is related to the nested object not being built when the dynamic section is added.

I have a normal fields_for and then a cocoon button to add additional items; the nested element is rendered in the normal fields_for section because I have built it specifically in my controller, but it is not rendered in the dynamically added section.

htowens

After some additional testing, I thought some clarification might be useful (I hope this is the same issue as you are having dnagir - please shout if not and I will move to a separate issue).

I can nest cocoon elements with no issues - that is to say, if I have a dynamically added section that has a link to add another nested dynamic section, everything works just fine. I tested this down to 3 levels, but I assume it would work for many more.

The problem occurs when I have a dynamically added form section that has a fields_for section for another object - the fields are never rendered because they are not built by cocoon (the action to build the object is only triggered when the nested elements are added dynamically).

I believe the approach to fix this may be to add a flag to the fields_for loop in the cocoon section so that cocoon know it needs to build that object in addition to the main object?

htowens

Having researched this a bit more, I agree with nathanvda that this is probably not directly related to Cocoon, but the Cocoon code is probably the easiest place to make it work, since the main model is being built anyway so it would be convenient to build the nested models (if indeed there is a way to access any nested models from the parent form builder - I have been stumped by how to do this, so have opened a SO question).

I would propose that this be converted to a feature request.

Nathan Van der Auwera
Owner

My answer to the SO question can be found here.

In short: build the nested object inside the partial, if the nested is always needed.

Taking dnagirs example, this would become something like

%tr.nested-fields{class: f.object.errors.any? ? 'error' : '' }
  %td
    = f.input :category, collection: Participation.category_hash.invert, include_blank: false, wrapper: :embeded
  - f.object.build_user  
  = f.simple_fields_for :user do |u|
    %td
      = u.input :email, wrapper: :embeded
    %td
      = u.input :first_name, wrapper: :embeded
    %td
      = u.input :last_name, wrapper: :embeded
  %td
    = link_to_remove_association "x", f, class: 'btn btn-danger btn-small'

Hope this helps.

Nathan Van der Auwera nathanvda closed this October 06, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.