Ajax pagination
ttp://wiki.github.com/mislav/will_paginate/ajax-pagination
This is the most popular feature request for will_paginate library. Reasons why the core library doesn’t support this are:
- pagination is a concept decoupled from HTTP requests and rendering;
- Ajax pagination is done differently across web frameworks;
- Ajax is done differently across JavaScript libraries (not everyone uses Prototype);
- The JavaScript side of the Ajax pagination concept is not trivial at all.
So the short reason why you can’t get Ajax pagination out-of-the-box with this library is that this kind of functionality belongs to user code.
Here are some examples to get you on the right track.
don’t use the “RemoteLinkRenderer” or similar solutions you might find on blogs using Rails’
link_to_remote
helper. Such solutions are obtrusive and will usually make your app broken for web spiders and difficult to debug.
Basic unobtrusive Ajax pagination for Rails
Let’s suppose you have a search box and you want to paginate search results. The following code assumes that:
- the partial that renders those results is named “search_results”;
- the same partial renders all the results wrapped in a DIV with an ID “results”;
- the “results” DIV also contains the pagination links;
- you have a graphic progress indicator (a “spinner”) saved in “images/spinner.gif”.
# app/views/posts/_search_results.html.erb
<div id="results">
<% for post in @posts %>
... render each post ...
<% end %>
<%= will_paginate @posts %>
</div>
First of all, make sure your controller responds to Ajax requests by updating the “results” DIV :
# app/controllers/posts_controller.rb
def index
@posts = Post.paginate :page => params[:page]
respond_to do |format|
format.html
format.js {
render :update do |page|
# 'page.replace' will replace full "results" block...works for this example
# 'page.replace_html' will replace "results" inner html...useful elsewhere
page.replace 'results', :partial => 'search_results'
end
}
end
end
Next, the unobtrusive JavaScript code:
# public/javascripts/application.js
document.observe("dom:loaded", function() {
// the element in which we will observe all clicks and capture
// ones originating from pagination links
var container = $(document.body)
if (container) {
var img = new Image
img.src = '/images/spinner.gif'
function createSpinner() {
return new Element('img', { src: img.src, 'class': 'spinner' })
}
container.observe('click', function(e) {
var el = e.element()
if (el.match('.pagination a')) {
el.up('.pagination').insert(createSpinner())
new Ajax.Request(el.href, { method: 'get' })
e.stop()
}
})
}
})