A collection of computer systems and programming tips that you may find useful.
 
Brought to you by Craic Computing LLC, a bioinformatics consulting company.

Wednesday, November 26, 2008

Rails - Drag and Drop Sorting in a Table

Through use of the Prototype and Script.aculo.us libraries, Rails makes it easy to set up drag and drop capability in your pages.

But all the examples I've seen use Lists of elements and I typically use Tables to display sets of data. I was having a hard time getting drag and drop sorting to work but I got there.

My problem was that I was putting my 'container id' into the <table> tag. That doesn't work. You have to have a <tbody> tag pair inside there - which I simply have never bothered with. Put the 'container id' in there and put the 'element id' in the <tr> tag - not the <td> tag.

In this dummy application you have carts and carts have multiple items. The order of each item in the cart is given by the item 'position' field.
class Cart < ActiveRecord::Base
has_many :items, :order => :position
end

class Item < ActiveRecord::Base
belongs_to :cart
acts_as_list :column => :position, :scope => :cart
end

This would go into your cart show page:
<table>
<tbody id="cart_div">
<% @cart.items.each do |item| %>
<tr id="item_<%= item.id %>">
<td><%= item.position %></td>
<td><%= item.name %></td>
</tr>
<% end %>
</tbody>
</table>

Then elsewhere in that page you need to add this block that sets up the JavaScript magic. Note that you need to specify the tag that will get dragged and dropped. The default is 'li' but here we want 'tr'.
<%= sortable_element 'cart_div',
:url => { :action => 'sort', :id => @cart },
:complete => visual_effect(:highlight, 'cart_div'),
:tag => 'tr'
%>

You also need to create a 'sort' action in your carts controller that looks something like this:
  def sort
@cart = Cart.find(params[:id])
@cart.samples.each do |cart|
item.position = params['cart_div'].index(item.id.to_s) + 1
item.save
end
render :nothing => true
end

Note that you don't need to do anything with your routes.rb file, even though 'sort' is not a standard action. I assume that is because it is using a GET and that just gets handled?

Finally, you need to include the javascript libraries in your page layout, but you knew that already.
<%= javascript_include_tag :defaults %>



4 comments:

dMan01 said...

Thanks a million. I was going nuts trying to figure this one out.

K said...

Throwing in tbody seems so simple - but it works. Thanks for the example!

springwind said...

Thanks a lot. just wondering how to highlight the row ...

Unknown said...

Thank you! Thank you!

Archive of Tips