如何使用 will_paginate gem 实现 ajax 分页

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13623953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 10:53:29  来源:igfitidea点击:

How to Implement ajax pagination with will_paginate gem

ajaxruby-on-rails-3will-paginate

提问by Mohammad Sadiq Shaikh

I am using will_paginategem in my RORproject to show the records in pages.

will_paginate在我的ROR项目中使用gem来显示页面中的记录。

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?

这该怎么做?

回答by Pierre Pretorius

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

使用以下内容创建一个新的助手(例如 app/helpers/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 的现有参数,您可以排除这些,如下所示。这是标准的分页功能:

<%= 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 questionwhere 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:我已经使它与远程兼容 Rails 4:真正的链接并将辅助方法重命名为js_will_paginate

回答by Akshay Vishnoi

Hey if you want to paginate products then try this:

嘿,如果您想对产品进行分页,请尝试以下操作:

app/controllers/products_controller.rb

应用程序/控制器/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

资产/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_pageoptions. Also we are rendering productspartial which will be rendered every time when other page is opened.

因此,首先我们为所有产品调用 Product 的 paginate 方法,这里将根据设置偏移量,params[:page]并通过per_page选项设置限制。此外,我们正在呈现products部分,每次打开其他页面时都会呈现。

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

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

Now in response to ajax request render content of divhaving class sort_paginate_ajaxwith the partial that we created.

现在响应 ajax 请求呈现div具有sort_paginate_ajax我们创建的部分的类的内容。

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

还要发出ajax请求,在文档中加载所有a标签的捕获脚本div.sort_paginate_ajax,并返回false。

Now pages will be called with ajax request

现在页面将被 ajax 请求调用

I hope this would help you.

我希望这会帮助你。

回答by sadnix

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_pagination_ajax”委托给子级“.pagination a”。

回答by A. Saloff

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:

分页.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 运行时再次设置链接数据远程。

回答by eaton9000

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 的优秀答案继续创建一个助手,我看到了一些关于更新视图的后续问题(我最初遇到的一个问题)。@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 %>');

回答by don_Bigote

I want to expand on Pierre's answer.

我想扩展皮埃尔的回答。

If you are using materialize sass with will_paginate_materialize then you will have an initializer to style the pagination links.

如果您将 materialize sass 与 will_paginate_materialize 一起使用,那么您将有一个初始化程序来设置分页链接的样式。

gem 'will_paginate', '~> 3.1.0'

gem 'will_paginate', '~> 3.1.0'

gem 'will_paginate-materialize', git: 'https://github.com/mldoscar/will_paginate-materialize', branch: 'master'

gem 'will_paginate-materialize', git: 'https://github.com/mldoscar/will_paginate-materialize', branch: 'master'

So, in order to get the remote true to work on the links rendered by the will_paginate_materialize initializer I did this:

因此,为了让遥控器真正在 will_paginate_materialize 初始值设定项呈现的链接上工作,我这样做了:

will_paginate_helper.rb

will_paginate_helper.rb

module WillPaginateHelper
  class WillPaginateJSLinkRenderer < WillPaginate::ActionView::LinkRenderer
  end
  def js_will_paginate(collection, options = {})
    will_paginate(collection, options.merge(:renderer =>WillPaginateHelper::WillPaginateJSLinkRenderer))
  end
end

I changed the will paginate materialize initializer to look like this:

我将 will paginate materialize 初始值设定项更改为如下所示:

will_paginate_materialize.rb

will_paginate_materialize.rb

MaterializePagination::MaterializeRenderer.module_eval do
  def page_number(page)
    classes = ['waves-effect', ('active' if page == current_page)].join(' ')
    tag :li, link(page, page, :rel => rel_value(page)), class: classes
  end

  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

WillPaginate::ViewHelpers::LinkRenderer.class_eval do
  def symbolized_update(target, other, blacklist = nil)
    other.each_pair do |key, value|
      key = key.to_sym
      existing = target[key]
      next if blacklist && blacklist.include?(key)

      if value.respond_to?(:each_pair) and (existing.is_a?(Hash) or existing.nil?)
        symbolized_update(existing || (target[key] = {}), value)
      else
        if value.instance_variable_defined?(:@parameters)
          value = value.instance_variable_get(:@parameters)
        end
        target[key] = value
      end
    end
  end
end

In my view I left the renderer in the will paginate link the same:

在我看来,我将渲染器留在了将分页链接中:

= will_paginate results, renderer: MaterializePagination::Rails

= will_paginate results, renderer: MaterializePagination::Rails