Sortable Drag and Drop
Hi
I am hoping someone can assist. I have gone through the tutorial of Srttable Drag and Drop.
https://gorails.com/episodes/sortable-drag-and-drop
All is working but once the drop happens I am getting a NoMethodError
NoMethodError (undefined method
each_with_index' for nil:NilClass):`
This is happening on the sort action in the controller (mine being admin/products)
def sort
params[:product].each_with_index do |id, index|
Product.where(id: id).update_all(position: index + 1)
end
head :ok
end
Anyone know what could be causing this ?
Hi Clay,
If you throw a byebug
in your action before you start iterating, you'll get a console where you can test what the params
are and see if the id's are even present in the params hash or that your key is actually :product
.
Can you post your view where you have your sortable list and the js?
Hi Jacob
Thanks for a idea. Here is the byebug result.
[1070, 1079] in /Users/Clayton/.rvm/gems/ruby-2.5.1/gems/actionpack-5.2.0/lib/action_controller/metal/strong_parameters.rb
1070: include ActiveSupport::Rescuable
1071:
1072: # Returns a new ActionController::Parameters object that
1073: # has been instantiated with the request.parameters.
1074: def params
=> 1075: @_params ||= Parameters.new(request.parameters)
1076: end
1077:
1078: # Assigns the given +value+ to the +params+ hash. If +value+
1079: # is a Hash, this will create an ActionController::Parameters
admin/products controller
def sort
params[:product].each_with_index do |id, index|
Product.where(id: id).update_all(position: index + 1)
end
head :ok
end
products.js
document.addEventListener("turbolinks:load", function() {
$("#products").sortable({
update: function(e, ui) {
Rails.ajax({
url: $(this).data("url"),
type: "PATCH",
data: $(this).sortable('serialize'),
});
}
});
});
Admin Products Index
<tbody id="products" data-url="<%= sort_admin_products_path %>">
<%= render @products %>
</tbody>
Admin Products - Product
<tr>
<td><%= link_to product.product_code, admin_product_path(product), id: dom_id(product) %> - (<%= product.position %>)</td>
<td><%= product.product_name.truncate(45) %></td>
<td></td>
<td><%= link_to 'Edit', edit_admin_product_path(product), class: 'btn btn-sm btn-warning' %></td>
<td><%=button_to "Remove", admin_product_path(product), method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-sm btn-danger' %></td>
</tr>
Ahh, I think your problem is how you're identifying your sortable objects. I haven't tested this or even done the sorting on a table so this could be wrong, but you're putting the id: dom_id(product)
on a <td>
tag and I believe it should be on the <tr>
tag.
As for the byebug result, you should do something like this:
def sort
byebug
params[:product].each_with_index do |id, index|
Product.where(id: id).update_all(position: index + 1)
end
head :ok
end
And then refresh the page. Now look at your terminal where you started your rails server at and you should now have a command prompt where you can type in params
then hit enter and get the params for that request. https://github.com/deivid-rodriguez/byebug
Sorry, small correction to the byebug instructions...
You'll refresh your page and then try rearranging your rows. The first time you move a row into a new slot it should fire the ajax request which should now trigger the byebug instance in your console. Now you can type in params
and see the params that were sent over in the request to see if you're getting anything at all related to your rearranged rows.
Hi thanks for the suggestions.
Here is the result of the params
"admin/products", "action"=>"sort"} permitted: false>
The Dom it is on the link_to tag within the td. Not sure if it should be moved out but here it is displaying correctly.
Displaying ok != working ok
Result of params shows that the ID's aren't being grabbed by the JS. So since all your code on the JS looks good, then the process of elimination is saying it's because you're defining your id on the <td>
instead of <tr>
Did you move id: dom_id(product)
to the <tr>
tag?
Please do that and then test. I just modified one of my implementations and it does not work if I put the ID on the <td>
tag but it works as expected when I move it to the <tr>
tag.