Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Implement ajax pagination with will_paginate gem

Tags:

I am using will_paginate gem in my ROR project to show the records in pages.

I want the next page to be loaded without reloading the whole page using ajax.

I found some examples on the net but they don't work for me.

How to do this?

like image 937
Mohammad Sadiq Shaikh Avatar asked Nov 29 '12 10:11

Mohammad Sadiq Shaikh


2 Answers

Create a new helper (ex. app/helpers/will_paginate_helper.rb) with the following content:

module WillPaginateHelper   class WillPaginateJSLinkRenderer < WillPaginate::ActionView::LinkRenderer     def prepare(collection, options, template)       options[:params] ||= {}       options[:params]['_'] = nil       super(collection, options, template)     end      protected     def link(text, target, attributes = {})       if target.is_a? Fixnum         attributes[:rel] = rel_value(target)         target = url(target)       end        @template.link_to(target, attributes.merge(remote: true)) do         text.to_s.html_safe       end     end   end    def js_will_paginate(collection, options = {})     will_paginate(collection, options.merge(:renderer => WillPaginateHelper::WillPaginateJSLinkRenderer))   end end 

Then in your view use this tag for ajax pagination:

<%= js_will_paginate @recipes %> 

Remember that the pagination links will include existing params of the url, you can exclude these as shown below. This is standard will paginate functionality:

<%= js_will_paginate @recipes, :params => { :my_excluded_param => nil } %> 

Hope that solves your problem.

Update 1: Added a explanation of how this works to the original question where I posted this solution.

Update 2: I've made it Rails 4 compatible with remote: true links and renamed the helper method to js_will_paginate.

like image 82
Pierre Pretorius Avatar answered Oct 06 '22 23:10

Pierre Pretorius


Hey if you want to paginate products then try this:

app/controllers/products_controller.rb

def index   @products = Product.paginate(page: params[:page], per_page: 10) end 

views/products/index.html.erb

<div class = "sort_paginate_ajax"><%= render 'products' %></div> 

views/products/_products.html.erb

<% @products.each do |product| %> # your code <% end %> <%= will_paginate @products %> 

views/products/index.js.erb

$('.sort_paginate_ajax').html("<%= escape_javascript(render("products"))%>") 

assets/javascripts/application.js

$(function() {   $(".sort_paginate_ajax th a, .sort_paginate_ajax .pagination a").on("click", function(){     $.getScript(this.href);     return false;   }); }); 

So first we are calling paginate method on Product for all products, here an offset will be set according to params[:page] and limit will be set by per_page options. Also we are rendering products partial which will be rendered every time when other page is opened.

In partial call on @products that you want, and then will_paginate method is applied on @products, it also creates params[:page] that is used in controller.

Now in response to ajax request render content of div having class sort_paginate_ajax with the partial that we created.

Also to make request ajax request, on document load capture script of all a tags in div.sort_paginate_ajax, and return false.

Now pages will be called with ajax request

I hope this would help you.

like image 43
Akshay Vishnoi Avatar answered Oct 06 '22 23:10

Akshay Vishnoi