您可以在没有直接嵌套关联的情况下使用coccon宝石吗?

时间:2019-04-01 11:53:44

标签: cocoon-gem

我必须将表单转换为不使用嵌套关联。换句话说,代替

<%= 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 %>

2 个答案:

答案 0 :(得分:0)

Cocoon当前无法编辑/管理集合。 Cocoon只是在帮助Rails中的嵌套子级功能的表单行为,因此没有简单的解决方案来编辑​​数组或集合。另一方面,这通常在没有茧的情况下很容易实现。

非常高级,请执行以下操作:

@contacts.each do |contact| 
  = render `contacts/edit`, contact: contact 
= render `contacts/new`

因此为每个现有联系人呈现编辑表单,并呈现一个空的新表单。您将不得不稍微修改控制器功能,因为您将始终重新渲染完整的集合/索引页面(集合中所有现有的联系人?)。

因此,您可以在一页上呈现多个表单。使用turbolinks可以快速渲染并感觉完全相同。您可以使用xhr来仅更新页面的特定部分,但是甚至不需要入门。

答案 1 :(得分:0)

因此,我最终遵循了drifting ruby,并使用了cocoon gem中的代码来自己实现了一些东西。我希望其他人可以从中受益。谢谢nathanvda提供的茧形宝石,它帮助了我以下代码,真的希望我可以使用它:

将此添加到您的 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>