Sorting of tables has been a trouble to many beginners as me. But I did stumble upon
this which helped me kick start the issue ( Well it almost did the job for me!).
We are going to use a couple of helpers to do almost all of the work for us. You may use me why helpers? Well it is to reinforce the DRYness of Rails. We can use the methods inside the over multiple views.
So if you want the helpers to be used across all the controllers the best place to put them is under /app/helpers/application_helper.rb else you could put it in your controller specific helper.
Here goes the code and the explanation of the helpers that we will be using.
The first helper is nothing but necessary. It is called sort_td_class_helper
, and his only goal is to add a class="sortup"
if the column is currently the one used to sort the table, or a class="sortdown"
if it is used to sort in reverse order. The only utility is to allow, with CSS, to indicates to the user which column is currently used as a sorting field.
The code is nothing interesting :
def sort_td_class_helper(param)
result = 'class="sortup"' if params[:sort] == param
result = 'class="sortdown"' if params[:sort] == param + " DESC"
return result
end
Then, we have a second helper, called sort_link_helper
.
def sort_link_helper(text, param)
key = param
key += " DESC" if params[:sort] == param
options = {
:url => {:overwrite_params => {:sort => key, :page => nil}},
:update => 'table',
:before => "Element.show('spinner')",
:success => "Element.hide('spinner')"
}
html_options = {
:title => "Sort by this field",
:href => url_for(:action => 'list', :params => @params.merge({:sort => key, :page => nil}))
}
link_to_remote(text, options, html_options)
end
This helper takes two arguments :
- text, which is just the text to be displayed as the column header and sort link
- param, which is the name of the request parameter associated with the column.
The first two lines define a new variable, called key
, which gets the value of the param
argument, ie the sort key. The string DESC
is concatenated to it if param
is already the sorting key. This is used to implement sorting in both ascending and descending order. If the user select a sort link, it will sort by ascending order ; if it selects the same link again, it will sort by descending order, and so on.
The rest of the helper is to define the options for the final call to the link_to_remote
function.
- the options hash, used for the javascript Ajax link, contains the
url
to be called to generate the new HTML, the id of the element to update, and two before
and success
actions to show/hide the spinner image. - the html_options hash, used for the HTML link. It generates the content of the
href
attribute with the url_for
Rails function.
Here is what the sort_link_helper
returns for a call with the strings "Title" and "title" as text
and param
arguments :
<a href="/item/list?sort=qty" onclick="Element.show('spinner'); new Ajax.Updater('table', '/item/list?sort=qty', {asynchronous:true, evalScripts:true, onSuccess:function(request){Element.hide('spinner')}}); return false;" title="Sort by this field">Quantity</a>
The view would use the helper function like
<td <%= sort_td_class_helper "name" %>>
<%= sort_link_helper "Name", "name" %>
</td>
The controller would use the
params[:sort] for obtaining the field to sort with and the manner in which it has to sort, i.e desc or asc.