【发布时间】:2012-11-17 10:02:48
【问题描述】:
我在我的ROR 项目中使用will_paginate gem 在页面中显示记录。
我希望在不使用ajax 重新加载整个页面的情况下加载下一页。
我在网上找到了一些例子,但它们对我不起作用。
如何做到这一点?
【问题讨论】:
标签: ajax ruby-on-rails-3 will-paginate
我在我的ROR 项目中使用will_paginate gem 在页面中显示记录。
我希望在不使用ajax 重新加载整个页面的情况下加载下一页。
我在网上找到了一些例子,但它们对我不起作用。
如何做到这一点?
【问题讨论】:
标签: ajax ruby-on-rails-3 will-paginate
创建一个具有以下内容的新助手(例如 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 %>
请记住,分页链接将包含 url 的现有参数,您可以排除这些,如下所示。这是标准的分页功能:
<%= js_will_paginate @recipes, :params => { :my_excluded_param => nil } %>
希望能解决您的问题。
更新 1:在我发布此解决方案的 original question 中添加了对其工作原理的说明。
更新 2:我已使其 Rails 4 与 remote: true 链接兼容,并将辅助方法重命名为 js_will_paginate。
【讨论】:
link_to_function 已弃用。你能把更新吗?提前致谢。
嘿,如果你想对产品进行分页,那么试试这个:
app/controllers/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>
views/products/_products.html.erb
<% @products.each do |product| %>
# your code
<% end %>
<%= will_paginate @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;
});
});
所以首先我们为所有产品调用 Product 的 paginate 方法,这里将根据params[:page] 设置偏移量,并通过per_page 选项设置限制。
此外,我们正在渲染 products 部分,每次打开其他页面时都会渲染。
在你想要的@products的部分调用中,然后应用will_paginate方法
@products,它还创建在控制器中使用的params[:page]。
现在响应 ajax 请求,呈现具有类 sort_paginate_ajax 的 div 的内容以及我们创建的部分内容。
同样做请求ajax请求,在div.sort_paginate_ajax中所有a标签的文档加载捕获脚本,并返回false。
现在页面将通过 ajax 请求调用
希望对你有帮助。
【讨论】:
/?_=1399023289230&page=3 的 url 中。我也将 .live() 更改为 .on(),谢谢
对上一个答案的补充。
代码串:
$(".sort_paginate_ajax th a, .sort_paginate_ajax .pagination a").on("click", function(){
用字符串替换:
$(".sort_paginate_ajax").on("click", ".pagination a", function(){
onclick 事件仅适用于已存在的元素。因此,对于新出现的链接,需要将父级“.sort_paginate_ajax”的点击事件委托给子级“.pagination a”。
【讨论】:
你可以只使用 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 %>
分页.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 运行时再次设置链接数据远程。
【讨论】:
我想扩展皮埃尔的答案。
如果您将 materialize sass 与 will_paginate_materialize 一起使用,那么您将有一个初始化器来设置分页链接的样式。
gem 'will_paginate', '~> 3.1.0'
gem 'will_paginate-materialize', git: 'https://github.com/mldoscar/will_paginate-materialize', branch: 'master'
所以,为了让远程 true 能够处理 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 初始化器更改为如下所示:
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
【讨论】:
为了继续 @Pierre 的出色回答,重新创建帮助程序,我看到了一些关于更新视图的后续问题(我最初遇到的问题)。 @Pierre 通过说明您需要创建一个 js 响应来跟进该问题。这是我在创建助手后所做的:
在我的 show.html.erb 中
<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 %>');
【讨论】: