Easy ajax sorting with will_paginate and ujs_sort_helper for rails

Install will_paginate

script/plugin install git://github.com/mislav/will_paginate.git

Install ujs_sort_helper

script/plugin install git://github.com/pengwynn/ujs_sort_helper.git

Install livequery

Livequery is just a javascript file. You can grab it from github (copy and paste is fine) and put it under public/javascripts/jquery.livequery.js.

Configure will_paginate and ujs_sort_helper together

Edit your controller’s list action. This example is nesting will_paginate and so is a little more complex than what you’ll probably use, but sometimes it’s rewarding to the reader to see a little bit more complexity. The key text to look at is the ‘options’ clause though.

1
2
3
4
5
6
7
8
9
10
11
12
13
  def show
    sort_init 'created_at'
    sort_update
    options = {:page => params[:page], :per_page => 10, :order => sort_clause }
 
    @project = Project.include_comments.include_watched_projects.find(params[:id])
    @comments = @project.comments.order_by.include_user.include_uploads.include_roles.paginate(options)
 
    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @project }
    end
  end

Configure application.rhtml with the necessary javascripts

My example is actually using jquery via the jrails plugin so if you are using prototype this might look a bit different. See the README for info on using prototype instead.

1
2
3
4
	<%= javascript_include_tag :defaults %>
	<%= stylesheet_link_tag "ujs_sort_helper"%>
	<%= javascript_include_tag "jquery.livequery.js" %>
	<%= javascript_include_tag "ujs_sort_helper.jquery.js", :plugin => "ujs_sort_helper"%>

Setup your view

I am not using the typical table so your example might be slightly different, but I figured it might be nice for other people to see how it functions without using a table.

In show.html.erb or list.html.erb or index.html.erb (whatever you used previously in your controller) place your will_paginate links and ujs_sort_helper link(s).

1
2
3
4
5
6
<!-- Comments -->
<div id="comments">	
	<p id="sort_comments" align="right"><%= sort_header_tag('created_at', :caption => 'Order') %></p>
	<%= render :partial => 'comments/comment', :collection => @comments %>
	<%= will_paginate @comments %>
</div>

As you can see, my code uses the sort_header_tag to create the sort link, and I am specifying the text caption with the :caption option. Then I am calling my comment partial with my array of @comments from the controller. And finally, I am including the pagination links using will_paginate and the array I want to paginate.

Edit ujs_sort_helper.jquery.js

We need this file to load the proper div for the ajax sort call.

1
2
3
4
5
6
7
8
9
10
11
12
13
 
 
jQuery(document).ready(function() {
	jQuery('a.sort_link').livequery('click', function(e) {
		jQuery('#comments').load(e.target.href + " div#comments"); 
		return false;
	});
 
	jQuery('div.pagination a').livequery('click', function(e) {
		jQuery('#comments').load(e.target.href + " div#comments"); 
		return false;
	});
});

Comments