Ajax Sortable Lists Rails 4
22 Dec 14
Learn how to easily achieve a drag and drop sortable lists functionality in your rails app that updates via ajax
With me, is a simple to-do list application where users can create dummy to-do lists and displays them in card-like form just like in Trello. We want to enable users to sort the list by drag and drop so that they are displayed in the specific order the user sets them.
You can take a sneak peek at the final result
To achieve the drag and drop functionality, we will be using
html5sortable jquery plugin. The reason I love this plugin as opposed to the widely used jQuery UI is its small size that means your page loads much faster while achieving the same functionality.
Grab the html5 sortable plugin form the
Github page. You can find the js in the
src directory. Add the
Next, lets require it in our application.js manifest file
Updating our Task Model
Our Task model has two fields,
description. We need to store the position of each of our tasks and to do this we need to add a
priority column which will store the position of our task inside the database. We will be able to sort our tasks by using this field.
rails g migration addPriorityToTasks priority:integer
rake db:migrate to update our database.
Let's take a look at our task's index view
As you can see, its pretty standard and all it does is render the
_task.html.erb partial. I have added a
.sortable class to the div that houses our partial, It is this class that we will call our sortable plugin on so that it sorts our tasks.
Next up,all we have to do is make our task's partial sortable. In the
tasks.js file, call sortable on our div with the sortable class
The sortable plugin will look for a
.sortable-placeholder class to use to show a placeholder while drag and droping our tasks. You can style it as you wish to suit your case
With this we should now have a drag and drop functionality
Our tasks in the list can now be dragged and dropped into any position, but the new order isn’t persisted back to the database. When we reload our page, the tasks are shown back in their default position.
We will add a
data-id attribute that will hold the id of the task and another attribute
data-pos that will hold the position of the task in the DOM. We will then send this attributes to our rails app each time the user has sorted the list and update the task's priority accordingly.
We then use jquery to set the
data-pos on each of our tasks
When we inspect our DOM you can now see that jquery did set the
data-pos for each of our tasks
Now that we have this in place, all we need is, after the user has finished sorting the tasks, we have to send the updated order back to rails. To do this, we will listen to the
sortupdate callback function provided by the html5sortable plugin. This function is triggered every time the user has stopped sorting and the DOM position has changed. We will add logic to get the updated order inside this callback function.
You will notice in the ajax call, we submit a PUT request to the sort_tasks_path (tasks/sort). We don't have this url set up yet. In our
Next up, we will have to write a method in our TasksController that will store the updated position orders. The controller currently has the standard RESTful actions for listing, showing and creating tasks. We will add a method
sort to our tasks controller that will be responsible for storing the updated task order as specified by the user.
The sort method will loop through the order parameter and update the priority for that Task. Each parameter contains the Task id and its new position. We find the Task by its id then update the priority attribute. Since we don’t need to send anything back from the AJAX call so the method finally returns nothing.
We will arrange our tasks based on the priority column. In the task model, lets add a
default_scope that orders our tasks based on the priority column in an ascending fashion.
And that's it!! Now when we drag the tasks about and then reload the page the items new position is persisted to the database. Hope this was helpful, have any questions or suggestions? feel free to use the comments sections below. You can also clone this app on my Github Repo.