0

I watched Railscast #196 on nested attributes and it was very helpful. I implemented on my project using Ryan's code as a guide and it works perfectly, except that the nested attribute I generate in the view is treated differently than subsequent ones which are dynamically created (when the Add Row link is clicked).

Let's start with the end - my params (abridged):

{"utf8"=>"✓", ... "slots_attributes"=>{"1429578951926"=>{"heading"=>"1", "description"=>"HEADING", "num_helpers"=>""}, "1429578953206"=>{"heading"=>"0", "description"=>"Parts", "num_helpers"=>"4"}}}, "slots"=>{"heading"=>"1", "description"=>"", "num_helpers"=>""}, "commit"=>"Submit", "controller"=>"sheets", "action"=>"create"}

My first nested attribute shows up as "slots" and the others are in "slots_attributes". I'd like them all in one place.

I'm guessing that may be enough information for someone out there to steer me in the right direction, but in case it isn't, I'll include the relevant code. Also, in case it is not clear, sheet has many slots.

My view:

.form-group#signup_details
  .row
    .col-md-2= label_tag "Heading?"
    .col-md-7= label_tag "Description"
    .col.md-3= label_tag "Number of helpers"
  = fields_for :slots do |builder|
    = render 'slot_fields', f: builder
  = link_to_add_fields "Add Row", sheet, :slots

The slot_fields partial:

.row.signup
  .col-md-2= f.check_box :heading
  .col-md-7= f.text_field :description, :class => "input-description", 
    :placeholder => "Heading, activity, item, time slot..."
  .col.md-3= f.text_field :num_helpers

link_to_add_fields helper in ApplicationHelper:

  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

Interesting parts of my models:

class Sheet < ActiveRecord::Base
  has_many :slots
  accepts_nested_attributes_for :slots
  attr_accessor :no_location, :misc_dates, :start_date, :start_time, :headcount_only, :slots_attributes

class Slot < ActiveRecord::Base
  belongs_to :sheet

Thanks in advance for your help!

UPDATE

My Javascript (in .coffee file just like he did on Railscast):

jquery -> 
  $('form').on 'click', '.add_fields', (event) ->
    time = new Date().getTime()
    regexp = new RegExp($(this).data('id'), 'g')
    $(this).before($(this).data('fields').replace(regexp, time))
    event.preventDefault()

The rest of my Javascript for this page is appended at the end of the page view file after a HAML :javascript tag.

And in my application layout file, I do have turbolinks enabled. Can I disable just for Javascript (and keep enabled for CSS)? I'll need to read up on them to recall the pros and cons.

= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true
= javascript_include_tag 'application', 'data-turbolinks-track' => true

1 Answer 1

1

In your view, try:

= f.fields_for :slots do |builder|

where f is the variable name you gave to the parent FormBuilder.

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

7 Comments

Didn't help but I have a related issue which could be impacting. When I click on the "Add Row" link, the attribute/row is not added and focus jumps to the top of the page. The link was previously doing that on initial load and now it happens every time. I am considering throwing it all out and implementing from scratch with AJAX. Thx for your advice.
What does your JavaScript to insert the new row look like? And do you have Turbolinks enabled? Turbolinks can interfere with JS handlers that get attached upon page load.
Thanks I've updated my question with JavaScript and something on Turbolinks. btw, I tried setting both CSS/JavaScript Turbolinks to false and restarting server and still the Add Row link is broken.
Update: On a whim, I converted the coffee script to JS and moved it to the end of my page view and the Add Row link is back! Works every time without needed page reload. Back to my original problem with params.
I have also added the parent FormBuilder to my fields_for call. It removed the (desired) blank child row from the form on initial render but any added rows get grouped in slots_attributes as expected. Last challenge (seems like it should be easy) is to add an empty child row to the initial form render so that it is grouped in slots_attributes with the user generated rows (when Add Row is clicked).
|

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.