How could I clone a child object in Rails using cocoon?

606 views Asked by At

I have a parent object with scores of children that are all very much alike. I have a form, with a table, to edit them using cocoon. With it (and this answer), I can add new rows to the table, and remove existing ones, and it works just fine.

What I'd like to do is add another button at the end of the row, to go along with the deletion button, to clone that row as the new row.

Parent form:

= simple_form_for @release, html: { multipart: true } do |f|
  = f.error_notification
  .col-md-12
    %table#myTable.table-striped.table-bordered
      %thead
        %tr
          %th Description
          ...
          %th Remove

      %tbody.codes
        = f.simple_fields_for :codes, wrapper: false do |code|
          = render 'code_fields', f: code
          ---> New code below would go here <---

    .links
      = link_to_add_association 'Add Code', f, :codes, data: {"association-insertion-node" => "tbody.codes", "association-insertion-method" => "append"}

    .form-actions
      = f.button :submit, class: 'btn btn-primary pull-right'

Child partial:

%tr.nested-fields
  = f.input :id, as: :hidden
  %td= f.input :description, label: false, input_html: { class: 'input-sm myinput' }
  ...
  %td
    = link_to_remove_association f, class: 'btn btn-default btn-xs' do
      .glyphicon.glyphicon-remove

I'd like to be able to add something like this to the last td element of the row:

= link_to_add_association 'Clone', f, :codes, data: {"association-insertion-node" => "tbody.codes", "association-insertion-method" => "append"}, render_options: {locals: {code: code.object}}

I have 2 issues. First, the way cocoon pre-generates the HTML to insert, I can't put this function call in the partial, because -- even if I were to get the syntax right -- it would create an infinite loop.

I'd be happy to work-around the problem by somehow jQuery-ing DOM nodes into place in the last cell of the appropriate table row if there were some way to "seed" the HTML generation with the values of the current object. At the point I want to insert the "clone" button, I have the current "code" child object in the code.object variable. (As code at this point is the fields_for form object.)

Is there any way to do this? render_options seems promising, but I can't figure out if this is just a syntax issue, or if the generator would never look at the hash of values I pass it in generating the fields.

1

There are 1 answers

2
nathanvda On BEST ANSWER

Take a look at the :wrap_object option, it allows to pre-initialize the object, I think you should be able to use it to clone from an existing object as well.

E.g. something like this might work:

- code_to_clone = f.object
= link_to_add_association('Clone', f, :codes,
    wrap_object: Proc.new { |new_code| new_code.name = code_to_clone.name; new_code })

Just copying 1 field for demonstration purposes :)