I was trying to implement a drag and drop list in my RoR web application, using the shopping cart demo from script.aculo.us as a template. But there was one problem. When I added and removed items from my "list", the entire list was rendered. In my case, this was worse than inefficient, since some of the "items" dropped into the list needed to be set up using calls to the database.
Now, in the excellent Agile Web Development with Rails book, in Chapter 18, they describe a method of "Dynamically Updating a List", which pretty much did what I wanted, which is just add or remove an "item" from my "list", only updating the item in question. No drag and drop, though.
The problem was figuring out how to combine these two examples into something that worked. The solution, as always in RoR, is almost childishly simple to implement, but I spent most of an afternoon figuring out those elegant, simple, 4 lines of code… :-}
In the interests of saving others that afternoon of fiddling, I figured I should post my solution. I’m simplifying things here. We are dealing with a simple "list" which contains "items", and when we drag an item into the list it gets added, and when we drag an item out of the list it gets removed. I’m not "counting" products like in the actual shopping cart demo.
For the drop_receiving element "list", add a position parameter, like:
:position => :top,
Then, in the add method, instead of:
render :partial => 'list'
use:
render :partial => 'list', :object => item
And in your remove method, instead of:
render :partial => 'list'
use:
render :inline => "Element.remove('item_#{i}');"
And for your drop_receiving_element "trash", change:
:complete => "Element.hide('indicator')"
to
:complete => "eval(request.responseText);Element.hide('indicator')"
Simple, eh? Hopefully I’ll soon have an external RoR server where I can post a working version with complete source.