Search code examples
ruby-on-railsruby-on-rails-4nested-forms

Rails: Delete nested form object dynamically


I have a form for add nested objects, like this:

This is the principal form:

#purchasing_goals.html.erb
<%= f.fields_for :group_goals do |builder| %>
    <%= render partial: 'group_goal_fields', locals: { f: builder } %>
<% end %>
<div>
<%= link_to_add_fields("Add", f, :group_goals) %>
</div>

and this is the nested form:

<div class="group-goal">
    <%= f.text_field :num_of_users, label: "No. Usuarios" %>
    <%= f.text_field :discount_percentage, label: "Descuento" %>
    <%= f.hidden_field(:_destroy) %>
    <%= link_to_remove_fields("Delete", f, "'.group-goal'") %>
</div>

and these are the helpers for add and remove group_goals items:

def link_to_remove_fields(name, f, removal_class)
     link_to name, "javascript:void(0);", onclick: "remove_fields(this, #{removal_class})"
    end

    def link_to_add_fields(name, f, association)
        new_object = f.object.class.reflect_on_association(association).klass.new
        fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
            render(association.to_s.singularize + "_fields", :f => builder)
        end
        link_to(name, "javascript:void(0);", onclick: "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")
    end

It works great, it adds a new item when you click the "Add" button, however when I click the "Delete" button it deletes the item in the form but not in the params of the form, so when I click the submit button an empty nested object is sent to the controller, How can I make the delete button delete the item not only in the form (visually) but also delete the created object?


Solution

  • You should use the following:

    <% content_tag :div, class: "group-goal", id: f.options[:child_index] do %>
        <%= f.text_field :num_of_users, label: "No. Usuarios" %>
        <%= f.text_field :discount_percentage, label: "Descuento" %>
        <%= f.hidden_field(:_destroy) %>
        <%= link_to "Remove", "#", class: "remove", %>
    <% end %>
    

    This will allow you to use the following:

    #app/assets/javascripts/application.js
    $(".group_goal a.remove").on("click", function(e){
       $(this).parents(".group_goal").remove();
    });
    

    You must remember that "dynamic" fields_for elements are simply HTML field elements, and thus can be removed from the DOM with javascript/jquery.


    You're using the old Railscast way of achieving this (those link_to_add_fields helper methods are outdated).

    The typical way to achieve it is to use the Cocoon gem, or to do it manually using answers like this: Rails accepts_nested_attributes_for with f.fields_for and AJAX