Ask A Question

Notifications

You’re not receiving notifications from this thread.

Sortable Drag and Drop

Clay asked in Rails

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 methodeach_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 ?

Reply

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?

Reply

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

Reply

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>
Reply

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

Reply

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.

Reply

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.

Reply

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.

Reply

Hi

Ok added as per your suggestion https://stackoverflow.com/questions/51676832/sortable-drag-and-drop-rails-jquery
Thanks once again have a great one!

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 81,842+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more.

    © 2024 GoRails, LLC. All rights reserved.