我试图用will_paginate gem实现一个Ajax调用,我发现这个指南http://ramblinglabs.com/blog/2011/11/rails-3-1-will_paginate-and-ajax看起来像一个简单的解决方案,虽然它包含了我不熟悉的coffeescript,所以如果有人有不同的解决方案那么请指教..
我的代码如下
我的观点
<div class="container">
<div class="row">
<div id="userRecipes">
<%= render partial: 'userrecipes' %>
</div>
</div><!--/row-->
我的部分(userrecipes)
<% @recipes.each do |r| %>
<div class="span3">
<div class="thumbnail">
<%= image_tag r.avatar.url(:myrecipes) %>
</div>
<h4><%= link_to r.dish_name, r %></h4>
<hr>
<p><%= truncate r.description, :length => 90 %></p>
<p><%= link_to "Edit Recipe", edit_recipe_path(r.id) %></p>
<p><%= link_to "Delete Recipe", recipe_path(r.id), :confirm => "Are you sure?", :method => :delete %></p>
<p><%= link_to "Add to favorites", {:controller => 'favourites', :action => 'create', :recipe_id => r.id}, {:method => :post } %></p>
</div><!--/span3-->
<% end %>
<%= will_paginate @recipes %>
更新了userrecipes.js.erb文件
$('#userRecipes').html('<%= escape_javascript(render partial: 'userrecipes') %>');
$.setAjaxPagination();
的CoffeeScript
$ ->
$.setAjaxPagination = ->
$('.pagination a').click (event) ->
event.preventDefault()
loading = $ '<div id="loading" style="display: none;"><span><img src="/assets/loading.gif" alt="cargando..."/></span></div>'
$('.other_images').prepend loading
loading.fadeIn()
$.ajax type: 'GET', url: $(@).attr('href'), dataType: 'script', success: (-> loading.fadeOut -> loading.remove())
false
$.setAjaxPagination()
当我点击下一个锚标记以显示下一组结果时,页面保持原样并且没有新内容出现
当使用控制台查看是否有任何错误时我可以看到任何错误,输出是
GET http://localhost:3000/my_recipes?page=2&_=1355055997639
我在这里遗漏了什么吗?或者我的userrecipes.js.erb文件有问题,因为在其他Ajax示例中我看到你在渲染部分时使用了escape_javascript吗?
修改
在检查控制台中的响应的同时,它还显示正在加载要加载的新配方,但视图中没有发生任何事情
赞赏任何指针
由于
答案 0 :(得分:11)
为什么不尝试一种更简单的方法,使用以下内容创建一个新助手(例如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 } %>
希望能解决你的问题。
<强>解释强>
Will_paginate允许您创建自己的自定义渲染器。 WillPaginateJSLinkRenderer是一个自定义渲染器,这个类可以在任何地方定义,它不必在辅助模块中定义。自定义渲染器扩展标准渲染器(LinkRenderer)并仅重新定义两种方法。
重写准备方法以显式删除cache buster parameter,因为will_paginate会创建包含呈现页面时存在的所有参数的页面网址,并且我们不想重复使用缓存区块参数。
链接方法是来自原始LinkRenderer source code的复制粘贴,但会创建一个与remote:true的链接,以使其成为JS resquest。
最后, js_will_paginate 方法是一个标准的视图助手方法,用于调用普通的will_paginate视图助手方法,但是将自定义渲染器添加到选项中,以便使用它而不是普通的渲染器。
答案 1 :(得分:3)
以防万一有人在寻找Rails 4解决方案。我喜欢皮埃尔·普雷托里乌斯(Pierre Pretorius)给出的答案,但是对于我来说4.1.1的&#34;方法未定义&#34; link_to_function 就行了:
@template.link_to_function(text.to_s.html_safe, ajax_call, attributes)
我刚刚将该行替换为:
@template.link_to(text.to_s.html_safe, '#', attributes.merge(:onclick => "#{ajax_call} event.preventDefault();"))
我希望它可以帮助别人。
答案 2 :(得分:2)
你没有逃避js.erb中的javascripts,这应该是问题所在。
$('#userRecipes').html('<%= escape_javascript(render partial: 'userrecipes') %>');
$.setAjaxPagination();
答案 3 :(得分:1)
ajax_will_paginate是一种极好的方法,但不幸的是它弄乱了分页的UI。我使用了另一种javascript方法以获得更大的灵活性。我在pageRender上调用了这个方法。
function checkForAjaxPaginate(controller,make_ajax){
var href = "";
$(".pagination").find("ul").each(function(){
$(this).find("li").each(function(){
$(this).find("a").each(function(){
href = $(this).attr("href");
if(href.indexOf(controller+".js") != -1){
if(make_ajax){
$(this).attr("data-remote","true");
}
else{
$(this).attr("href",href.replace(".js",""));
}
}
});
});
});
}
为了获得更大的灵活性,您只需在“controller”变量中传递操作名称,如果要将其转换为ajax,则将true传递给make_ajax。我所做的就是检查href链接是否为“.js”,如果make_ajax为true,则添加attr“data-remote = true”,在我们的ROR应用程序中将其设为ajax。如果make_ajax不是真的那么我只是删除“.js”所以代码不会乱。 我希望这有帮助
答案 4 :(得分:1)
皮埃尔·普雷托里乌斯的答案很棒,但是我必须多做一点才能让它对我有用,但目前还不清楚。也许这会对其他初学者有所帮助。
除了制作助手并使用js_will_paginate
标签,我还是这样做了:
在移动内容之后,我尝试将其分页为部分(在上面的情况下为_recipes.html.erb
),我还创建了一个show.js.erb
文件(在此部分的同一视图中),文本类似于这样:
$('#recipes').html('<%= escape_javascript(render partial: 'recipes') %>');
然后我必须将js_will_paginate标记移动到部分和底部(因此它会在我分页或点击下一个/上一个时更新)。然后我不得不将渲染部分帮助器包装在你在js文件中定位的div id中,所以在这个例子中:
<div id="recipes">
<%= render partial: "recipes" %>
</div>
这可能对其他人来说非常清楚,但我不确定OP必须保留哪些步骤,哪些步骤是不必要的。这些步骤对我有用。您不需要在控制器中添加respond_to js,因为帮助程序会处理或拥有coffeescript文件。