client side validation for multi level nested field_for did not generate validation attribute #423

Closed
jzinedine opened this Issue Oct 29, 2012 · 18 comments

5 participants

@jzinedine

Rails version: 3.2.8
client_side_validation: current git

Sample HTML code:

Customer form:

<%= customer_form.fields_for :person do |f| %>
    <div class="field">
     <%= f.label :firstname %>
     <%= f.text_field :firstname %>
   </div>
   ....
   <%= render "address_fields", :person_form => f %>
and ....

Person partial view:
<% @customer.person.addresses.each_with_index do |address, index| %>
    <%= person_form.fields_for :addresses, address, :validate => true do |f| %>
        <div id="pane<%= index + 2 %>" class="tab-pane">
          <div class="field">
            <%= f.label :category %>
            <%= f.select :category, address_categories_options, {:include_blank => true} %>
          </div>
 and ....
class Customer < ActiveRecord::Base
    belongs_to :person
....
end

class Person < ActiveRecord::Base

  has_one :customer
  has_many :addresses, :dependent => :destroy
....
end

class Address < ActiveRecord::Base
  belongs_to :person
....
end
@bcardarella

Can I get the full resulting HTML?

@jzinedine

If it doesn't make any inconvenience my app is running at http://leasing-rahbar.herokuapp.com/customers/new on heroku.

Source code is also available at https://github.com/jzinedine/leasing

Thanks for quick reply

@jzinedine

Let me ask a more clear question:
Does this gem support deep nested attributes (deep nested fields_for)?

Here you can find the full HTML code:

https://gist.github.com/3992265

One of the input which lacks the validation requirements despite the necessary declarations in class is : customer_person_attributes_addresses_attributes_0_part .

@bcardarella
@jzinedine

But in README file there is an item (# 7) which clearly states that this functionality is in progress now :

7 Validate nested fields

Update 0:

I think I got closer to the root cause:
As you can see in first post addresses partial would be generated by a loop on address collection, but what would be generated in page refer to non-existing element and actually is wrong.
For example in the generated script there exists a part like this:

"validators":{"customer[person_attributes][addresses_attributes][][part1]":
    {"presence":[{"message":"blahblahblah"}]}, 

which must be
javascript customer[person_attributes][addresses_attributes][0][part1]
or
customer[person_attributes][addresses_attributes][1][part1]

anyway it lacks the index part.

Update 1:
If I inspect the @validators hash in ruby ClientSideValidations::ActionView::Helpers::FormHelper#fields_for, I will see the wrong information which seed the clien_side_validations gem:
This is an item from @validators hash:

:category=>
    {:name=>"customer[person_attributes][addresses_attributes][][category]",
     :options=>nil},

Let me repeat that this problem occur for a fields_for block which nest in another fields_for block.

@fauzieuy

+1 i have same issue
validation not generate for nested field_for

new.html.erb :

<%= form_for(@admin :url => registration_path(resource_name), :validate => true) do |f| %>
           <%= f.fields_for :account do |inner_form|%>
                   <div  class="field">
                         <%= inner_form.label :name, "Your Name" %>
                         <%= inner_form.text_field :name %>
                    </div>
           <% end %>

           <div class="field">
                    <%= f.label :email, "Email" %>
                    <%= f.email_field :email %>
            </div>

             <div>
                      <%= f.submit "Sign up" %>
             </div>
<% end %>
class Account < ActiveRecord::Base    

    has_one :admin

    validates_presence_of :name

end
class Admin < ActiveRecord::Base
   belongs_to :account

   accepts_nested_attributes_for :account

   validates_presence_of :email
end

html code :

<div class="field"><label for="admin_account_attributes_name">Name</label>
                      <input id="admin_account_attributes_name" name="admin[account_attributes][name]" size="30" type="text" data-validate="true"></div>

but not generate

look screenshoot :
Form

@bcardarella

I cannot seem to recreate this. Would it be possible for someone to create a demo app for this issue?

@fauzieuy

@bcardarella validate show if change :account to @account

<%= f.fields_for :account, :validate => true do |inner_form|%>

to

<%= f.fields_for @account, :validate => true do |inner_form|%>

but this is not nested form... any ideas?

@fauzieuy

@bcardarella problem solved bro,
sorry, this is my fault because i have two the same name of nested form..

@bcardarella

@fauzieuy your solution does "work" but it the first example should also work. I believe this is still an open bug but I cannot recreate it :p

@fgrehm

Hey guys, I while ago I had this idea of creating "tiny little" Rails apps (inspired by this gist) to try out new gems and to support bug reports. A couple of weeks ago I was able to release a gem to help out creating these spikes.
If guys wanna try it I'd be more than happy to help you out (just shoot me an email or create an issue over there so we dont "polute" this issue ;-), any kind of feedback would also be great.
Cheers

@bcardarella

@jzinedine I'm having a difficult time navigating the app as it is all in Iranian. Can you create a demo in English?

@ansel1

I'm also hitting this. Looking now for the root cause.

@ansel1

K, @fauzieuy explained it, but I didn't understand. The problem occurs if you have multiple fields_for nested in a single outer form, and the fields_for are for the same associated object:

<%= simple_form_for @user , :validate => true do |f| %>

          <%= f.simple_fields_for :profile do |d| %>
              <%= d.input :first_name %>
              <%= d.input :last_name %>
          <% end %>
          <%= f.input :email %>
          <%= f.input :password %>
          <%= f.simple_fields_for :profile do |d| %>
              <%= d.input :telephone %>
          <% end %>
<% end %>

The intent is simply to layout out some of the profile attributes at the beginning of the form, and some at the end. Innocent enough. But due to this line: (https://github.com/bcardarella/client_side_validations/blob/3-2-stable/lib/client_side_validations/action_view/form_helper.rb#L54)

    def fields_for(record_or_name_or_array, record_object = nil, options = {}, &block)
      output = super
      @validators.merge!(options[:validators]) if @validators
      output
    end

the second time through this method will wipe out validators captured the first time through. I.e. the validator hash for :telephone will overwrite the hash for :first_name and :last_name

I'm going to experiment with this:

<%= simple_form_for @user , :validate => true do |f| %>

          <%= f.simple_fields_for :profile do |d| %>
              <%= d.input :first_name %>
              <%= d.input :last_name %>
                  <%= f.input :email %>
                  <%= f.input :password %>
              <%= d.input :telephone %>
          <% end %>
<% end %>
@ansel1

Yup, that works.

@jzinedine

@bcardarella I think if you change the local to en you can go through the generated HTML.

@bcardarella

@ansel1 ah, fantastic. I can fix that

@bcardarella bcardarella added a commit that referenced this issue Nov 22, 2012
@bcardarella bcardarella Resolve multiple nested fields_for
Closes #423
9ef1275
@bcardarella

Ok, this should be resolved. Please user the 3-2-stable branch in your Gemfile and let me know if there are any further issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment