0

I built a form_for with 4 associated models. I created nested fields_for which can be added dynamically with the code below. My form works if I call the 'edit' method but if I use the method below to add new data the fields_for remains empty and are not shown.

def link_to_add_fields(name, f, association)
    new_object = f.object.send(association).klass.new
    id = new_object.object_id
    fields = f.fields_for(association, new_object, child_index: id) do |builder|
      render(association.to_s.singularize + "_fields", f: builder)
    end
    link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
  end

This works fine if I only wants to add one form of a model. But if the added content which have fields_for for nested fields_for the text_fields are not created. In my opinion it is because I do not build the associations. How can I fix this method to do this?

1 Answer 1

1

I have a very similar method (based on Itay Grudev's blog post), in which I set the child_index as nil and then use jQuery to replace it with a timestamp (so that many records can be added avoiding them having the same id).

So, in my application_helper.rb file I've got:

def link_to_add_fields(name = nil, f = nil, association = nil, options = nil, html_options = nil, &block) 
    f, association, options, html_options = name, f, association, options if block_given? 
    options = {} if options.nil? 
    html_options = {} if html_options.nil? 

    if options.include? :locals 
      locals = options[:locals]
    else 
      locals = { } 
    end 
    if options.include? :partial 
      partial = options[:partial] 
    else 
      partial = association.to_s.singularize + '_fields'
    end 

    new_object = f.object.class.reflect_on_association(association).klass.new 
    fields = f.fields_for(association, new_object, child_index: nil) do |builder| 
      render(partial, locals.merge!( fields: builder)) 
    end 

    html_options['data-form-prepend'] = raw CGI::escapeHTML( fields ) 
    html_options['href'] = '#'

    content_tag(:a, name, html_options, &block) 

end

And then I added a Coffeescript file called dynamic_tables.js.coffee in which I find the newly added fields, replace their name with a timestamp (so they're all indexed as a group) and prepend the form to a target (a hidden element I added at the bottom of my table and marked it as prepend_target). So I've got:

$('[data-form-prepend]').click (e) ->
    target = $($(this).attr('prepend_target'))
    obj = $($(this).attr('data-form-prepend'))
    current_time = (new Date).getTime()
    obj.find('input, select, textarea').each ->
      $(this).attr 'name', ->
        $(this).attr('name').replace 0, current_time
      return
    obj.insertBefore target
    false

That should do the trick. Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.