问题
I have to convert my form to not using nested association. In other words, instead of
<%= link_to_add_association f, :contacts, class: 'btn btn-primary', partial: 'projects/contact_fields', data: {
association_insertion_node: '.contact_fields', association_insertion_method: :append
} do %>
<i class="fas fa-plus"></i>
<% end %>
<%= f.fields_for :contacts do |contact| %>
<%= render 'projects/contact_fields', f: contact %>
<% end %>
I would like to be able to just pass in a string to be used as the container (similar to how you can with field_for).
<%= link_to_add_association 'contacts[]', 'projects/contact_fields', class: 'btn btn-primary', partial: 'projects/contact_fields', data: {
association_insertion_node: '.contact_fields', association_insertion_method: :append
} do %>
<i class="fas fa-plus"></i>
<% end %>
<% @contacts.each_with_index do |contact, index| %>
<%= fields_for "contacts[#{index}]", contact do |c| %>
<%= render 'projects/contact_fields', f: c %>
<% end %>
<% end %>
回答1:
Cocoon is currently unable to edit/manage a collection. Cocoon is just helping the form-behaviour for nested-children functionality in rails, so there is no simple solution to edit an array or collection. On the other hand, this is in general pretty simple to implement without cocoon.
Very high level, do something like:
@contacts.each do |contact|
= render `contacts/edit`, contact: contact
= render `contacts/new`
so render the edit form for each existing contact, and render an empty new form. You will have to edit your controller functionality a little, because you will always re-render the complete collection/index page (with all existing contacts in the collection?).
So you can just render multiple forms on one page. Using turbolinks this will render fast and feel actually completely the same. You could use xhr to update only specific parts of the page, but to get started that is not even needed.
回答2:
So I ended up following drifting ruby and using code from the cocoon gem to implement something myself. I hope others can benefit from it. Thank you nathanvda for the cocoon gem which helped me with the code below, really wish I could have used it:
add this to your app/helpers/application_helper.rb
def link_to_add_row(*args, &block)
if block_given?
link_to_add_row(capture(&block), *args)
else
#byebug
name, association, new_object, partial, html_options = *args
html_options ||= {}
html_options[:class] = [html_options[:class], "custom_add_fields"].compact.join(' ')
id = 'NEW_RECORD'
fields = fields_for("#{association}[#{id}]", new_object, child_index: id) do |builder|
#byebug
render( partial, f: builder)
end
fields = CGI.escapeHTML(fields).html_safe
link_to(name, '#', class: html_options[:class], data: {id: id, fields: fields})
end
end
add to your app/assets/application.js
$(document).on('click', '.custom_remove_fields', function(event) {
$(this).prev('input[type=hidden]').val('1');
$(this).closest('tr').hide();
return event.preventDefault();
});
$(document).on('click', '.custom_add_fields', function(event) {
var regexp, time;
time = new Date().getTime();
regexp = new RegExp($(this).data('id'), 'g');
$('.contact_fields').append($(this).data('fields').replace(regexp, time));
return event.preventDefault();
});
In your template you can use the following to render a partial for the collection:
<%= link_to_add_row('contacts', contact.new, 'contact_fields', class: 'btn btn-primary') do %>
<i class="fas fa-plus"></i>
<% end %>
This is how I render the partial with the collections in my template:
<tbody class="contact_fields">
<% @contacts.each_with_index do |contact, index| %>
<%= fields_for "contacts[#{index}]", contact do |c| %>
<%= render 'contact_fields', f: c %>
<% end %>
<% end %>
</tbody>
This is what my contact_fields.html.erb partial looks like.
<tr class="nested-fields">
<td>
<%= f.text_field :fullname, class: 'form-control invoke-contacts-search contact-fullname' %>
</td>
<td>
<%= f.text_field :email, class: 'form-control invoke-contacts-search contact-email' %>
</td>
<td>
<%= f.text_field :phone, class: 'form-control contact-phone' %>
</td>
<td>
<%= f.text_field :department, class: 'form-control contact-department' %>
</td>
<td>
<%= f.text_field :manager, class: 'form-control contact-manager' %>
</td>
<td>
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy %>
<%= link_to '#', class: 'btn btn-danger custom_remove_fields' do %>
<i class="fas fa-trash-alt"></i>
<% end %>
</td>
</tr>
来源:https://stackoverflow.com/questions/55454504/can-you-the-coccon-gem-without-a-direct-nested-association