如何使用will_paginate gem实现ajax分页

时间:2012-11-29 10:42:17

标签: ajax ruby-on-rails-3 will-paginate

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

我希望加载下一页而不使用ajax重新加载整个页面。

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

怎么做?

6 个答案:

答案 0 :(得分:32)

使用以下内容创建一个新助手(例如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

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

<%= js_will_paginate @recipes %>

请记住,分页链接将包含网址的现有参数,您可以将其排除,如下所示。这是标准的分页功能:

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

希望能解决你的问题。

更新1 :在我发布此解决方案的original question中添加了有关其工作原理的说明。

更新2 :我已将Rails 4与remote:true链接兼容,并将帮助方法重命名为 js_will_paginate

答案 1 :(得分:17)

嘿,如果你想分页产品,那么试试这个:

应用程序/控制器/ products_controller.rb

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

视图/产品/ index.html.erb

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

视图/产品/ _products.html.erb

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

视图/产品/ index.js.erb的

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

资产/ Javascript角/ application.js中

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

首先,我们在所有产品的Product上调用paginate方法,此处将根据params[:page]设置偏移量,并且per_page选项将设置限制。 此外,我们渲染products部分,每次打开其他页面时都会渲染。

@products上进行部分通话,然后应用will_paginate方法 @products,它还会创建控制器中使用的params[:page]

现在响应ajax请求呈现内容div,其中sort_paginate_ajax类包含我们创建的部分。

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

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

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

答案 2 :(得分:5)

除了之前的回答。

代码串:

m x n

替换为字符串:

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

onclick事件仅适用于已存在的元素。因此,对于新出现的链接,需要委托来自父级&#34; .sort_paginate_ajax&#34;的点击事件。给孩子&#34; .pagination a&#34;。

答案 3 :(得分:2)

你可以使用JQuery:

控制器:

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

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

然后在index.html.erb中:

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

在部分'_post_content.html.erb'中:

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

pagination.js:

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

index.js.erb的:

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

确保添加

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

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

答案 4 :(得分:0)

为了继续@ Pierre的优秀答案重新创建帮助,我已经看到一些关于更新视图的后续问题(我最初遇到的问题)。 @Pierre通过声明您需要创建一个js响应来跟进该问题。这是我在创建帮助程序后所做的事情:

在我的show.html.erb

window

我创建了另一个名为show.js.erb的文件(因此show的两种格式)

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

答案 5 :(得分:0)

我想扩大皮埃尔的答案。

如果将willize_paginate_materialize与物化sass结合使用,则将有一个初始化器来设置分页链接的样式。

gem 'will_paginate', '~> 3.1.0'

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

因此,为了使远程控件能够在will_paginate_materialize初始值设定项呈现的链接上工作,我做到了:

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

我将遗嘱实现实例化器更改为如下形式:

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

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

= will_paginate results, renderer: MaterializePagination::Rails