2

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?

2 Answers 2

3

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

Sign up to request clarification or add additional context in comments.

2 Comments

If I remove it from the DOM it will be removed from the params?
Yes it will. The fields are only HTML - removing them is a case of getting rid of the HTML elements which make up the form, and they shouldn't be available to pass into the params hash
-1

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

1 Comment

Thanks! I had the dependent: :destroy on the association, but I was missing the allow_destroy: true in the model.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.