如何使用will_paginate gem实现ajax分页?

时间:2022-02-02 14:30:14

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

我在ROR项目中使用will_paginate以页面形式显示记录。

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

我希望在不使用ajax重新加载整个页面的情况下加载下一页。

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

我在网上找到了一些例子,但它们对我不起作用。

How to do this?

如何做到这一点呢?

5 个解决方案

#1


27  

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

创建一个新助手(ex. app/helper /will_paginate_helper.rb),内容如下:

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:

然后在您的视图中使用此标记进行ajax分页:

<%= 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:

请记住,分页链接将包括url的现有参数,您可以将其排除在下面。这是标准的will分页功能:

<%= 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.

更新1:在我发布这个解决方案的原始问题中添加了一个说明。

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

更新2:我使它与remote: true链接兼容,并将helper方法改名为js_will_paginate。

#2


16  

Hey if you want to paginate products then try this:

如果你想对产品进行分页,试试这个:

app/controllers/products_controller.rb

app / controllers / products_controller.rb

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

views/products/index.html.erb

视图/产品/ index.html.erb

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

views/products/_products.html.erb

视图/产品/ _products.html.erb

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

views/products/index.js.erb

视图/产品/ index.js.erb

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

assets/javascripts/application.js

资产/ javascript / 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.

首先,我们调用产品上的paginate方法,这里将根据params[:page]设置一个偏移量,而per_page选项将设置limit。我们也在渲染产品的部分,每次打开其他页面时都会渲染。

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.

在对您想要的@products的部分调用中,然后将will_paginate方法应用于@products,它还创建用于controller的params[:page]。

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

现在,作为对ajax请求的响应,div的渲染内容具有类sort_paginate_ajax和我们创建的部分。

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

还要对div.sort_paginate_ajax中的所有标记进行文档加载捕获脚本请求,并返回false。

Now pages will be called with ajax request

现在将使用ajax请求调用页面

I hope this would help you.

我希望这能对你有所帮助。

#3


3  

Additional to previous answer.

另外之前的答案。

string of code:

字符串的代码:

$(".sort_paginate_ajax th a, .sort_paginate_ajax .pagination a").on("click", function(){

replace with string:

替换字符串:

$(".sort_paginate_ajax").on("click", ".pagination a", function(){

The onclick event applied only to the elements that already exist. So, for new appears links, need delegate click event from parent ".sort_paginate_ajax" to childs ".pagination a".

onclick事件只应用于已经存在的元素。因此,对于新建的显示链接,需要从父节点委托单击事件。sort_paginate_ajax“孩子”。分页”。

#4


1  

You could just use JQuery:

你可以用JQuery:

Controller:

控制器:

def index
  @posts = Post.paginate(:page => params[:page])      

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

Then in index.html.erb:

然后在index.html.erb:

<div id="post-content", posts: @posts >
  <%= j render 'post_content' %>
</div>

In partial '_post_content.html.erb':

部分“_post_content.html.erb”:

<%= will_paginate @posts %>
<% @posts.each do |post| %>
  <p><%= post.content %></p>
<% end %>

pagination.js:

pagination.js:

$(document).ready(function() {
  $('.pagination > a').attr('data-remote', 'true');
});

index.js.erb:

index.js.erb:

$('#post-content').html("<%= j render 'post_content' %>")

Make sure to add the

一定要加上

$('.pagination > a').attr('data-remote', 'true');

again in your JS template (index.js.erb), so it sets the links data-remote again when the Ajax runs.

在您的JS模板(index.js.erb)中,它再次设置了Ajax运行时的链接数据远程。

#5


0  

To follow on from @Pierre's excellent answer re creating a helper, I've seen some follow up questions regarding updating the views (a problem I initially had). @Pierre follows up with that problem by stating that you need to create a js response. Here's what I did after creating the helper:

按照@Pierre的出色答案re create a helper,我看到了一些关于更新视图的后续问题(这是我最初遇到的问题)。@Pierre继续这个问题,指出您需要创建一个js响应。以下是我创建助手后所做的:

in my show.html.erb

在我show.html.erb

<div id="see-comments">
    <%= render @comments %>
</div>
<div id="pagination-comments">
    <%= js_will_paginate @comments %>
</div>

I created another file called show.js.erb (so two formats for show)

我创建了另一个名为show.js的文件。erb(显示有两种格式)

// to update comments    
$("#see-comments").html("<%= j render @comments %>");
// to update the pagination links
$("#pagination-comments").html('<%= js_will_paginate @comments %>');

#1


27  

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

创建一个新助手(ex. app/helper /will_paginate_helper.rb),内容如下:

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:

然后在您的视图中使用此标记进行ajax分页:

<%= 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:

请记住,分页链接将包括url的现有参数,您可以将其排除在下面。这是标准的will分页功能:

<%= 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.

更新1:在我发布这个解决方案的原始问题中添加了一个说明。

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

更新2:我使它与remote: true链接兼容,并将helper方法改名为js_will_paginate。

#2


16  

Hey if you want to paginate products then try this:

如果你想对产品进行分页,试试这个:

app/controllers/products_controller.rb

app / controllers / products_controller.rb

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

views/products/index.html.erb

视图/产品/ index.html.erb

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

views/products/_products.html.erb

视图/产品/ _products.html.erb

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

views/products/index.js.erb

视图/产品/ index.js.erb

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

assets/javascripts/application.js

资产/ javascript / 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.

首先,我们调用产品上的paginate方法,这里将根据params[:page]设置一个偏移量,而per_page选项将设置limit。我们也在渲染产品的部分,每次打开其他页面时都会渲染。

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.

在对您想要的@products的部分调用中,然后将will_paginate方法应用于@products,它还创建用于controller的params[:page]。

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

现在,作为对ajax请求的响应,div的渲染内容具有类sort_paginate_ajax和我们创建的部分。

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

还要对div.sort_paginate_ajax中的所有标记进行文档加载捕获脚本请求,并返回false。

Now pages will be called with ajax request

现在将使用ajax请求调用页面

I hope this would help you.

我希望这能对你有所帮助。

#3


3  

Additional to previous answer.

另外之前的答案。

string of code:

字符串的代码:

$(".sort_paginate_ajax th a, .sort_paginate_ajax .pagination a").on("click", function(){

replace with string:

替换字符串:

$(".sort_paginate_ajax").on("click", ".pagination a", function(){

The onclick event applied only to the elements that already exist. So, for new appears links, need delegate click event from parent ".sort_paginate_ajax" to childs ".pagination a".

onclick事件只应用于已经存在的元素。因此,对于新建的显示链接,需要从父节点委托单击事件。sort_paginate_ajax“孩子”。分页”。

#4


1  

You could just use JQuery:

你可以用JQuery:

Controller:

控制器:

def index
  @posts = Post.paginate(:page => params[:page])      

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

Then in index.html.erb:

然后在index.html.erb:

<div id="post-content", posts: @posts >
  <%= j render 'post_content' %>
</div>

In partial '_post_content.html.erb':

部分“_post_content.html.erb”:

<%= will_paginate @posts %>
<% @posts.each do |post| %>
  <p><%= post.content %></p>
<% end %>

pagination.js:

pagination.js:

$(document).ready(function() {
  $('.pagination > a').attr('data-remote', 'true');
});

index.js.erb:

index.js.erb:

$('#post-content').html("<%= j render 'post_content' %>")

Make sure to add the

一定要加上

$('.pagination > a').attr('data-remote', 'true');

again in your JS template (index.js.erb), so it sets the links data-remote again when the Ajax runs.

在您的JS模板(index.js.erb)中,它再次设置了Ajax运行时的链接数据远程。

#5


0  

To follow on from @Pierre's excellent answer re creating a helper, I've seen some follow up questions regarding updating the views (a problem I initially had). @Pierre follows up with that problem by stating that you need to create a js response. Here's what I did after creating the helper:

按照@Pierre的出色答案re create a helper,我看到了一些关于更新视图的后续问题(这是我最初遇到的问题)。@Pierre继续这个问题,指出您需要创建一个js响应。以下是我创建助手后所做的:

in my show.html.erb

在我show.html.erb

<div id="see-comments">
    <%= render @comments %>
</div>
<div id="pagination-comments">
    <%= js_will_paginate @comments %>
</div>

I created another file called show.js.erb (so two formats for show)

我创建了另一个名为show.js的文件。erb(显示有两种格式)

// to update comments    
$("#see-comments").html("<%= j render @comments %>");
// to update the pagination links
$("#pagination-comments").html('<%= js_will_paginate @comments %>');