Tuesday, November 22, 2011

AJAX pagination in rails 3

      We all use will_paginate gem for pagination in our application. However the pagination sends a HTTP request every time when you click on the next page. It will be very nice if the pagination sends an ajax request and update the corresponding <div>, well here it is and its very easy in rails 3... you just have to add few lines in views and controller.

1. In the controller

def index
    @devices = Devices.all.paginate(:page => params[:page] || 1, :per_page => 10)
    .....
    .....

    respond_to do |format|
      format.html
      format.js
    end
end

2. Create a file named index.js.erb in the views and place the following code.

$('#devices').html('<%=escape_javascript(render(:partial => "devices_list"))%>');
$('.pagination a').attr('data-remote', 'true');

3. Put the table which has pagination inside a partial, so that it can be called on each ajax request.

I wish to use pagination in one of my index page, So i will place my table inside a partial  _devices_list.html.erb

<table>
      <thead>
        <tr >
          <th>&nbsp;</th>
          <th colspan="2"><h4>Devices</h4></th>
          <th><%= will_paginate(@devices, :previous_label => "&larr; Previous", :next_label => "Next &rarr;", :inner_window => 1, :outer_window => 1 )%></th>
        </tr>
......
......
</table>

and place this partial inside a div

<div id="devices">
  <%= render :partial => 'devices_list' %>
</div>

4. Add a few lines of jquery inside the script tag in the index page

 <script type="text/javascript">
  $(function() {
    $('.pagination a').attr('data-remote', 'true');
  });
</script>

That's it... it's all done... now you can see an index page which has ajax pagination.If you wish to notify the user that something is happening with a spinner or any hourglass image when the user clicks on the pagination link add the following code.

Add a div which contains the image of the spinner in index file or application.html.erb(This can be used all over the application).

<div id="show_spinner_image" style="display: none">
  <%=image_tag('loader.gif', :border => "0", :style => "float:left;")%> 
</div>

In your application.css

#show_spinner_image{
  position: fixed;
  top: 50%;
  left: 55%;
  margin: -100px 0 0 -100px;
  text-indent: 250px;
  white-space: nowrap;
  overflow: hidden;
}

This CSS will display the spinner at the center of the screen.

Inside the script tag :

<script type="text/javascript">
  $(function() {
     $('.pagination a').click(function(){
         $('#show_spinner_image').show();
        $('.pagination a').attr('data-remote', 'true');
      });
  });
</script>
And at last, in your index.js.erb

$('#devices').html('<%=escape_javascript(render(:partial => "devices_list"))%>');
$('#show_spinner_image').hide();
$('.pagination a').click(function(){
$('#show_spinner_image').show();
$('.pagination a').attr('data-remote', 'true');
     });


Enjoy......