nestedSortable with closure_tree gem in Rails

418 Views Asked by At

Web team of a customer was asking me for a fast solution to drag'n drop sort their categories of products on their admin dashboard. Here's my solution working fast and perfectly without lots of code.

Here's the closure_tree gem, making models acting as nodes in a tree data structure : https://github.com/ClosureTree/closure_tree

And here's nestedSortable for the JS part.

Here's my view :

<ul class="sort" data-url="<%= sort_admin_catalog_categories_path %>">
<% categories.each do |c| %>
    <%= content_tag_for :li, c do %>
        <ul>
            <%= c.name.upcase %>
            <% if c.child? then %>
                <% c.children.each do |c1| %>
                <%= content_tag_for :li, c1 do %>
                    <ul>
                        <strong><%= c1.name %></strong>
                            <% if c1.child? then %>
                                <% c1.children.each do |c2| %>
                                    <%= content_tag_for :li, c2 do %>
                                    <%= c2.name %>
                                    <% end %>
                                <% end %>
                            <% end %>
                        <% end %>
                    </ul>
                <% end %>
            <% end %>
        </ul>
    <% end %>
<% end %>

JS :

$(document).ready(function() { 
    $('.sort').nestedSortable({
        items: 'li',
        update: function(e, ui) {
        Rails.ajax({
          url: $(this).data("url"),
          type: "PATCH",
          data: $(this).nestedSortable('serialize'),
        });
        }
    });
});

Route :

  resources :categories do
    collection do
      patch :sort
    end
  end

Controller :

  def sort
    params[:category].each_with_index do |id, index|  
        Category.where(id: id).update_all({sort_order: index+1})
    end
    head :ok
  end

Notice that since Rails 5.1 you should use params[:category].to_unsafe_h.each_with_index or build a relative method for strong params

Finally the nestedSortable options :

    options: {
        disableParentChange: false,
        doNotClear: false,
        expandOnHover: 700,
        isAllowed: function() { return true; },
        isTree: true,
        listType: "ul",
        maxLevels: 0, //infinite
        protectRoot: false,
        rootID: null,
        rtl: false,
        startCollapsed: false,
        tabSize: 20,

If it can help.

N.B. : I didn't solved yet the deal of N+1 if someone wants to contribute I would really appreciate.

0

There are 0 best solutions below