Skip to content
This repository was archived by the owner on May 28, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ The `nested_fields_for` method lists the phones this person has and also adds an

If you're paying attention, you noticed the key elements are marked with special class names. We *need* this for the javascript code, so it knows what to do with each HTML element: the one that have the children must have the class `items`; each child must be marked with the class `item`; inside an item, the link for removal must have the class `remove`; and the link to add new items must have the class `add`. We can change the names later, but these are the default choices. Finally, don't forget to add the `id` field, as it is needed by AR to identify whether this is an existing or a new element, and the `_destroy` field to activate deletion when the user clicks on the remove link.

### JSONB collections
To use this with a JSONB collection instead of an association, use the `new_object` and `collection` options.

Use collection to pass in the array, new_object to pass in what an empty object looks like.

```erb
<%= f.nested_fields_for :phones, collection: f.object[:phones],
new_object: [OpenStruct.new({number: ''})] do |f| %>
<fieldset class="item">
<%= f.label :number %>
<%= f.text_field :number %>

<a href="#" class="remove">remove</a>

<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy %>
</fieldset>
<% end %>
```

### Javascript

This is the easiest part: just activate the nested fields actions when the page loads. We can put this in the `application.js` file (or in any other place that gets executed in the page):
Expand Down
10 changes: 8 additions & 2 deletions lib/rails/form_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@ def nested_fields_for(association, options={}, &block)
raise ArgumentError, 'Missing block to nested_fields_for' unless block_given?

options[:new_item_index] ||= 'new_nested_item'

options[:collection] = options[:collection].map{ |o| OpenStruct.new(o) } if options[:collection]
options[:new_object] ||= self.object.class.reflect_on_association(association).klass.new
options[:item_template_class] ||= ['template', 'item', association.to_s.singularize].join(' ')
options[:empty_template_class] ||= ['template', 'empty', association.to_s.singularize].join(' ')
options[:show_empty] ||= false
options[:render_template] = options.key?(:render_template) ? options[:render_template] : true
options[:escape_template] = options.key?(:escape_template) ? options[:escape_template] : true

output = @template.capture { fields_for(association, &block) }
if options.key? :collection
output = @template.capture { fields_for(association, options[:collection], &block) }
else
output = @template.capture { fields_for(association, &block) }
end
output ||= template.raw ""

if options[:show_empty] and self.object.send(association).empty?
output.safe_concat @template.capture { yield nil }
end
Expand Down