svelandiag
svelandiag

Reputation: 4320

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?

Upvotes: 2

Views: 3662

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

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

Upvotes: 3

akbarbin
akbarbin

Reputation: 5105

I guest you have to ensure several steps to fix it. Check your strong parameter in your controller and add _destroy and id

def hotel_params
  params.require(:purchasing_goal).permit(:your_own_field, group_goals_attributes: [ :id, :num_of_users, :discount_percentage, :_destroy ])
end

Next, check your purchasing_goal.rb model to add allow_destroy: true

accepts_nested_attributes_for :group_goals,
                                reject_if: proc { |attributes| attributes['num_of_users'].blank? },
                                allow_destroy: true

I hope this help you. For more information nested_forms-rails-4.2

Upvotes: -1

Related Questions