nathanvda / cocoon

Dynamic nested forms using jQuery made easy; works with formtastic, simple_form or default forms
http://github.com/nathanvda/cocoon
MIT License
3.08k stars 385 forks source link

save model position #551

Closed fmorton closed 5 years ago

fmorton commented 5 years ago

Cocoon has been very easy to use and is great, but I have been unable to figure out how to get it to save the final order when the form is submitted. The model associated with each "ibox" has a "position" attribute. But, it does not seem to get set and I have been unable to discover how to cause the position to be set. Any pointers?

nathanvda commented 5 years ago

"Any pointers?" sounds a bit rude. It sounds like: "I do not want to put too much time in giving you extra information, and I have no time to read through all the issues, so you please list all possible things that could go wrong when saving a model in rails."

I understand the problem is very clear for you, but this is incredibly vague. Not sure how you expect a good answer if you don't even want to invest some time in providing some information so I at least understand what you are working with, I have no idea what "the final order", "ibox", "position" mean. Could you please show: the model associations, the strong parameter definition, and what is posted to the controller.

For now I assume: a "final order" has many "ibox" which has an attribute "position" which is most likely set by some kind of drag/drop/re-order library?

Pointers:

(also very kind to say it is easy to use and great, but does that mean you have used it before, or is this the first time you use it --because that also puts a different light on the situation)

fmorton commented 5 years ago

Points well taken. I have been using rails since 1.0, but first time using Cocoon. Using Rails 5 with ruby 2.5.3.

This is a brand new app. It is also a complex situation where I am using jquery "sortable" with a bootstrap theme allowing the nested attributes to be sequenced via draggable panels.

The base model is "projects" that looks like this:

class Project < ApplicationRecord has_many :project_steps, -> { order(position: :asc) }, :dependent => :destroy

accepts_nested_attributes_for :project_steps, :allow_destroy => true, :reject_if => :reject_if_proc

def reject_if_proc(attributes) attributes['name'].blank? end

A project can have many "project_steps" which look like this:

class ProjectStep < ApplicationRecord belongs_to :project, :optional => true end

The ProjectStep model has a "position" attribute which is expected to be an integer storing the sequence of the project steps.

The form looks like this (with clutter removed):

<%= form_with(model: @project, local: true) do |form| %> [snip] Name: <%= form.text_field :name %>

<%= form.submit %>
<%= form.simple_fields_for :project_steps do |builder| -%> <%= render 'project_step_fields', :f => builder %> <% end -%>
<%= link_to_add_association "Add Project Step", form, :project_steps, :class => 'btn tbn-primary', :data => { :association_insertion_node => '.project_steps', :association_insertion_method => :append } %>

<% end %>

<% content_for :javascript do %>

<% end %>

It all works surprisingly well, but when saving, the "position" attributes for the project_steps does not get set, so a reload of the page goes back to the original sorting order.

Would the normal cocoon behavior include setting the project_steps.position?

When I look at the params when submitting the form, the "params[:project][:project_steps_attributes]" are not in the resorted order of the draggable panels, so I am at a loss if the issue is with cocoon (because position is not normally updated) or with the jquery draggable panels only being reordered visually and not submitted with the form in the sorted order.

Thanks.

PS You can see a very early version of this working as described at: https://www.makernotebook.org/projects/4/edit

nathanvda commented 5 years ago

Thank you for the information! That is helpful! (it would more helpful still if you would format your code better 😛)

You call it "normal cocoon behaviour" but cocoon only helps in dynamically rendering the nested forms. So normal rails behaviour is to save everything that is 1) posted to the controller, and 2) allowed by the strong parameters definition. You have not shown either, so a bit hard to tell.

It is entirely unclear to me how you expect the position attribute to be set at all?

But using sortable together with cocoon is not a new problem. Does #200 help?

nathanvda commented 5 years ago

Additionally, I see two options to store the position: either set the position in the controller based on the received order of arrays, or use js to correctly set the position (which should be a hidden field). See here: https://stackoverflow.com/questions/2979643/jquery-ui-sortable-position

Does that help you?

nathanvda commented 5 years ago

Closed due to inactivity.