Как реализовать AJAX pagination с помощью will paginate gem

Я использую will_paginate камень в мой для отображения записей на странице.

Я хочу, чтобы следующая страница была загружена без перезагрузки всей страницы с помощью ajax.

Я нашел несколько примеров в интернете, но они не работают для меня.

как это сделать?

5 ответов


создайте нового помощника (ex. 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 pagination:

<%= js_will_paginate @recipes %>

помните, что ссылки разбиения на страницы будут включать существующие параметры url-адреса, вы можете исключить их, как показано ниже. Это стандартная функция разбиения на страницы:

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

надеюсь, это решит вашу проблему.

обновление 1: добавлено объяснение того, как это работает для исходный вопрос где я разместил это решение.

обновление 2: Я сделал его Rails 4 совместимым с remote: true links и переименовал вспомогательный метод в js_will_paginate.


Эй, если вы хотите разбить продукты на страницы, попробуйте следующее:

app / контроллеры / products_controller.rb

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

просмотры / продукты / индекс.формат html.Эрб

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

вид/продукты/_products.формат html.Эрб

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

просмотры / продукты / индекс.js.Эрб

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

активы / javascripts / приложение.js

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

Итак, сначала мы вызываем метод разбит на продукте для всех продуктов, здесь смещение будет установлен по к params[:page] и предел будет установлен per_page параметры. Также мы оказываем products частичный, который будет отображаться каждый раз, когда открывается другая страница.

в частичном вызове на @products что вы хотите, а потом will_paginate метод применяется на @products, он также создает params[:page] что используется в контроллере.

теперь в ответ на ajax запрос рендеринга содержимого div класса sort_paginate_ajax С частичным, который мы создали.

также сделать запрос ajax запрос, на загрузку документа скрипт захвата всех a теги div.sort_paginate_ajax, и возвращать false.

теперь страницы будут вызываться с запросом ajax

я надеюсь, это поможет вам.


дополнительно к предыдущему ответу.

строку кода:

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

заменить строку:

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

событие onclick применяется только к уже существующим элементам. Итак, для новых ссылок, нужно делегировать событие click от родителя ".sort_paginate_ajax "to childs".pagination a".


вы можете просто использовать JQuery:

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

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

затем в индексе.формат html.Эрб:

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

пагинации.js:

$(document).ready(function() {
  $('.pagination > a').attr('data-remote', 'true');
});
.js.Эрб:
$('#post-content').html("<%= j render 'post_content' %>")

добавьте

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

снова в вашем шаблоне JS (индекс.js.erb), поэтому он снова устанавливает ссылки data-remote при запуске Ajax.


чтобы следовать из @ Pierre's excellent answer re создание помощника, я видел некоторые последующие вопросы, касающиеся обновления представлений (проблема, которую я изначально имел). @Pierre следует за этой проблемой, заявив, что вам нужно создать ответ js. Вот что я сделал после создания помощника:

в моем шоу.формат html.Эрб

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

Я создал еще один файл под названием show.js.erb (так что два формата для шоу)

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