link_to_sort

Posted by Tom Willett Fri, 16 Feb 2007 16:46:00 GMT

I have created a little view helper that I use in my ROR applications. I call it link_to_sort. What it does is create a clickable header on a list page that sorts the list by that header.

I add it to the application helper and make minimal changes to the controller list action and add one routine to the application controller to make it work.

Here is the code for the helper:
  def link_to_sort(title, field_name)
    txt= '<a href="/' + @controller.controller_name + '/' + @controller.action_name + '?direction=' + @ndir + '&order=' + field_name + '">' + title + '</a>'
    if @order == field_name
      if @direction == 'ASC'
        txt += '<img alt="Arrow-up" class="dirimg" src="/images/arrow-up.png" />'
      else
        txt += '<img alt="Arrow-down" class="dirimg" src="/images/arrow-down.png" />'
      end
    end
    return txt
  end

As I mentioned, put this in app/helpers/application_helper.rb and it will be available to all your views. This assumes that you have two small images in you images directory called arrow-up.png and arrow-down.png to represent the direction of sort. I will leave that to the reader to supply.

To the application controller (app/controllers/application.rb) add the following routine:

  def get_order(default_order, default_direction = 'ASC')
    @order = params[:order] || default_order
    params[:direction] = 'DESC' if default_direction == 'DESC' and params[:direction] != 'ASC'
    if params[:direction] == 'ASC'
      @ndir = 'DESC'
    else
      @ndir = 'ASC'
    end
    @direction = params[:direction] || 'ASC'
    if @direction != 'ASC'
      @direction = 'DESC'
    end
    @od = @order.sub(',',' ' + @direction + ',') + ' ' + @direction
  end

With these two pieces of code in place, modifying your views and controllers to take advantage of sortable headers in the list view is simple

First modify the controller by adding:

:order => get_order('id')

To the end of the line that sets up paging for the list. So for example if you had a list of contacts the paging line would look like:

@contact_pages, @contacts = paginate :contacts, :per_page => 10, :order => get_order('id')

By the way the 'id' in the examples is the default sort column and can be changed to match your needs

Now in the view, replace your headings like:

<th>Name</th><th>City</th> ......

With

<th><%= link_to_sort 'Name', 'lastname, firstname' %></th>
<th><%= link_to_sort 'City', 'city' %></th> .....

As you might have guessed the two parameters that link_to_sort take are the Label for the column and the actual sort columns. You will notice in the first example you can give multiple columns for the sort. The first time you click the column will be sorted ascending and the second time you click it will be sorted descending.

A little arrow will appear beside the column when sort is active showing the direction of sort

Comments

Leave a comment

Comments