JQuery UI: Submitting a Sortable Widget
JQuery UI has a great widget called Sortable, where you can drag and drop items in place to… you guessed it, it sorts the items. This is great and all, but one of the reasons you may want to have this interactive UI is to reorder some list the user owns. In this post, we’ll take a look at one implementation of persisting newly sorted items in order to the database. This method will not use AJAX to submit the form.
If you want to follow along, go ahead and fork this Github repo. I’ve created branches for the major checkpoints.
Setup
Let’s pretend that we’re making a photo album application, where we have photos that belong to an album. We want to show the photos in a particular order so when we edit the album, we should be able to use the Sortable widget and submit a form to persist the new order into the database.
I’ve set up the bare-bones configuration before we actually start implementing the Sortable widget. This can be found on the GitHub repo as branch “1_base_config”. It’s a very standard Rails MVC setup except for that photo is a nested resource under album. As a result, in order to create any photos, you must create an album first, then add photos. I recommend forking, running the rails server, and test out the flow of the resources.
Before_create hooks
Note that we have an order attribute and a token attribute on the Photo model. The order is somewhat self-explanatory, but we’ll see soon why we need the token attribute. Both of these fields should be auto generated by the system when the photo is created.
First, open up the model folder and find the Photo.rb file. We’re going to create 2 private methods that will automatically generate the order and token on the “before create” hook.
In general, these methods should be broken out to different concerns so that it’s reusable across model, but we’ll save that for another blog post. You can test out that these hooks are working by starting the Rails server and creating some photos.
Sortable Widget
The next step is to implement the sortable widget. For this example, we’ll use just the photo description, but you can imagine that the actual image could be used as part of the UI. Additionally, as part of the configuration, the JQuery UI library has already been included in the vendor/assets folder and the application.
First, setup a list item of all the album photos in views/albums/edit.html.erb. In order to turn it into a Sortable widget, make sure that the <ol> tag has an id of “sortable”.
Then in the empty app/assets/javascripts/sortable.js, call the JQuery UI sortable function on the unordered list element.
Now, if you access the Edit Order page, the list items should be sortable by dragging and dropping the items.
Submit and persist the Sortable widget
The final step is to wrap a form around the sortable widget and submit the information. Let’s start by modifying the edit.html.erb view.
In the above code, we’ve added a form_for
for the album and added some required markup on the form_for
and the li
tag. It is important to note that the id attribute of the li
tag is the randomly generated token. This way, we don’t expose the database IDs of the photo to the users. Lastly, there is an text input field. This will be populated by the order of the photos before the form is submitted using the Javascript code presented below from the sortable.js file:
The photoSorter.submit function will take the ID attributes from the sortable elements and covert it into an array. Afterwards, it will populate the value of the text field with the array. Once the form is submitted, params should look similar to the following:
In the Album Controller, we need to make a few modifications. We first need to use strong params to sanitize the tokens and then on the update action, call Album#update_order
and pass in the order params. We should also implement the Album#update_order
method on the Album model:
The methods can be refactored some and abstracted out to a PhotoSorter class, but for the sake of this example, we’ll keep it as is. Now if you take a look at the album page, the photos have a new order in the Order column. As a final touch you can hide the text input field on the “Edit Photo Order” page so it is hidden from the users. The final product can be found in the “master” branch or the “3_persist_order”.
Another implementation of using the Sortable widget with a form can be achieved by using AJAX to send the information. We’ll save that for another blog post. Until next time happy coding!
Reference: http://stackoverflow.com/questions/5131460/using-jqueryui-sortable-list-with-forms