Rails 3.1 - will_paginate and AJAX
November 10, 2011
This post was originally published in the Rambling Labs Blog on November 10, 2011.
For a project that I’m currently working on, I have a couple of list views that needed pagination. So I went with the ol’ will_paginate
gem (which I first saw years ago when I didn’t even consider myself a developer) to take care of this.
It’s as simple as including a line with gem 'will_paginate'
on your Gemfile
, running bundle install
, and include this in the controller:
class OrdersController < ApplicationController
def index
@orders = Order.paginate(page: params[:page], per_page: 10)
end
end
And this in the view orders/index.html.erb
:
<div id="orders">
<ul>
<% @orders.each do |order| %>
<li>
<!-- Show order stuff -->
</li>
<% end %>
</ul>
<%= will_paginate @orders %>
</div>
Now, this last line will generate your pagination links. Then, a problem arose. There was one specific view which I didn’t want to be refreshed completely when clicking the pagination links.
Partials, jQuery and AJAX to the rescue
I found a post (in a blog with a really familiar name), which described a way to do it that just seemed magical. But that combined with a stack overflow question that I found, seems to be the way to go. Here is what I did:
In the controller:
class OrdersController < ApplicationController
def index
@orders = Order.paginate(page: params[:page], per_page: 10)
end
end
Encapsulate the order list in the partial view orders/_orders.html.erb
:
<ul>
<% @orders.each do |order| %>
<li>
<!-- Show order stuff -->
</li>
<% end %>
</ul>
<%= will_paginate @orders %>
The resulting index view orders/index.html.erb
:
<div id="orders">
<%= render partial: 'orders' %>
</div>
The view orders/index.js.erb
:
$('#orders').html('<%= render partial: 'orders' %>');
$.setAjaxPagination();
The JavaScript (CoffeeScript) file assets/orders.js.coffee
:
$ ->
$.setAjaxPagination = ->
$('.pagination a').click (event) ->
event.preventDefault()
loading = $ '<div id="loading" style="display: none;"><span><img src="/assets/loading.gif" alt="cargando..."/></span></div>'
$('.other_images').prepend loading
loading.fadeIn()
$.ajax type: 'GET', url: $(@).attr('href'), dataType: 'script', success: (-> loading.fadeOut -> loading.remove())
false
$.setAjaxPagination()
And that’s it! Fairly easy I would say!