我必须将我的表单转换为不使用嵌套关联。换句话说,而不是
<%= 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 %>
我希望能够传入一个字符串来用作容器(类似于你如何使用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 %>
Cocoon目前无法编辑/管理集合。 Cocoon只是帮助rails中的嵌套子功能的表单行为,所以没有简单的解决方案来编辑数组或集合。另一方面,这通常很容易实现,没有茧。
非常高的水平,做类似的事情:
@contacts.each do |contact|
= render `contacts/edit`, contact: contact
= render `contacts/new`
因此,为每个现有联系人呈现编辑表单,并呈现一个空的新表单。您将不得不稍微编辑控制器功能,因为您将始终重新呈现完整的集合/索引页面(集合中的所有现有联系人?)。
因此,您只需在一个页面上呈现多个表单即可。使用turbolinks,这将快速呈现,感觉实际上完全相同。您可以使用xhr仅更新页面的特定部分,但是要开始甚至不需要。
所以我最终关注drifting ruby并使用cocoon gem中的代码自己实现一些东西。我希望其他人可以从中受益。感谢nathanvda为我提供了下面代码的cocoon gem,真的希望我能用它:
将此添加到您的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
添加到您的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();
});
在模板中,您可以使用以下内容为集合呈现部分:
<%= link_to_add_row('contacts', contact.new, 'contact_fields', class: 'btn btn-primary') do %>
<i class="fas fa-plus"></i>
<% end %>
这就是我在模板中使用集合渲染部分的方法:
<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>
这是我的contact_fields.html.erb部分看起来像。
<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>