简体   繁体   English

使用will_paginate gem在rails 3.2.3中调用Ajax

[英]Ajax call in rails 3.2.3 with will_paginate gem

Im trying to implement an Ajax call with the will_paginate gem, I found this guide http://ramblinglabs.com/blog/2011/11/rails-3-1-will_paginate-and-ajax which seemed like a simple solution, though it includes coffeescript which i am not familiar with, so if anyone has a different solution then please advise.. 我试图用will_paginate gem实现一个Ajax调用,我发现这个指南http://ramblinglabs.com/blog/2011/11/rails-3-1-will_paginate-and-ajax这似乎是一个简单的解决方案,尽管它包括我不熟悉的coffeescript,所以如果有人有不同的解决方案,请告知..

My code is as follows 我的代码如下

My View 我的观点

<div class="container">
 <div class="row">
  <div id="userRecipes">
   <%= render partial: 'userrecipes' %>
 </div>
</div><!--/row-->

My partial (userrecipes) 我的部分(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 %>

updated userrecipes.js.erb file 更新了userrecipes.js.erb文件

$('#userRecipes').html('<%= escape_javascript(render partial: 'userrecipes') %>');
$.setAjaxPagination();

Coffeescript 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()

When i click on the next anchor tag to show the next set of results the page stays as it is and no new content appears 当我单击下一个锚标记以显示下一组结果时,页面保持原样并且不显示新内容

When using the console to see if there are any errors i can see any, the output is 使用控制台查看是否有任何错误我可以看到任何错误,输出是

GET http://localhost:3000/my_recipes?page=2&_=1355055997639

Am i missing something here? 我错过了什么吗? or is there an issue with my userrecipes.js.erb file because in other Ajax examples i have seen thy are using escape_javascript when rendering the partial? 或者我的userrecipes.js.erb文件是否存在问题,因为在其他Ajax示例中我看到你在渲染部分时使用的是escape_javascript?

Edit 编辑

Whilst inspecting the response in the console it is also showing that the new recipes to be loaded are being loaded but nothing is happening in the view 在检查控制台中的响应时,它还显示正在加载要加载的新配方但视图中没有发生任何事情

Any pointers appreciated 任何指针赞赏

Thanks 谢谢

Why not try a simpler approach, 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. 请记住,分页链接将包含URL的现有参数,您可以将其排除,如下所示。 This is standard will paginate functionality: 这是标准的分页功能:

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

Hope that solves your problem. 希望能解决你的问题。

Explanation: 说明:

Will_paginate allows you to create your own custom renderer . Will_paginate允许您创建自己的自定义渲染器 The WillPaginateJSLinkRenderer is such a custom renderer and this class could be defined anywhere, it doesn't have to be defined inside the helper module. WillPaginateJSLinkRenderer是一个自定义渲染器,这个类可以在任何地方定义,它不必在辅助模块中定义。 The custom renderer extends the standard renderer (LinkRenderer) and redefines only two methods. 自定义渲染器扩展标准渲染器(LinkRenderer)并仅重新定义两种方法。

The prepare method is overriden to explicitly remove the cache buster parameter since will_paginate creates the page urls with all parameters that were present when rendering the page and we do not want to reuse the cache buster parameter. prepare方法被覆盖以显式删除缓存buster参数,因为will_paginate使用呈现页面时存在的所有参数创建页面URL,并且我们不想重用cache buster参数。

The link method is a copy paste from the original LinkRenderer source code but creates a link with remote: true to make it a JS resquest. link方法是来自原始LinkRenderer源代码的复制粘贴,但是创建了一个与remote:true的链接,以使其成为JS resquest。

Finally the js_will_paginate method is a standard view helper method to call the normal will_paginate view helper method but adds our custom renderer to the options so that it will be used instead of the normal renderer. 最后, js_will_paginate方法是一个标准的视图助手方法,用于调用普通的will_paginate视图助手方法,但是将自定义渲染器添加到选项中,以便使用它而不是普通的渲染器。

Just in case someone is looking for Rails 4 solution. 以防万一有人在寻找Rails 4解决方案。 I liked the answer from Pierre Pretorius, but it failed for me on 4.1.1 with "method undefined" for link_to_function on the line: 我喜欢皮埃尔·普雷托里乌斯(Pierre Pretorius)给出的答案,但是对于我来说,在4.1.1中我没有使用“方法未定义”来为线路上的link_to_function

@template.link_to_function(text.to_s.html_safe, ajax_call, attributes)

I just replaced the line to: 我刚刚将该行替换为:

@template.link_to(text.to_s.html_safe, '#', attributes.merge(:onclick => "#{ajax_call} event.preventDefault();"))

I hope it may help someone. 我希望它可以帮助某人。

You are not escaping javascripts in your js.erb, it should be the problem. 你没有逃避js.erb中的javascripts,这应该是问题所在。

$('#userRecipes').html('<%= escape_javascript(render partial: 'userrecipes') %>');
$.setAjaxPagination();

The ajax_will_paginate is a superb method, but unfortunately it was messing up the UI of the paginate. ajax_will_paginate是一种极好的方法,但不幸的是它弄乱了分页的UI。 I had employed another javascript method for more flexibility. 我使用了另一种javascript方法以获得更大的灵活性。 And I call this method on pageRender. 我在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",""));
                    }
                }
            });
        });
    });
}

For more flexibility, you just pass the action name in the "controller" variable and pass true to make_ajax if you want to convert it to ajax. 为了更加灵活,您只需在“controller”变量中传递操作名称,如果要将其转换为ajax,则将true传递给make_ajax。 All I am doing is to check if the href link is ".js", and if make_ajax is true, then adding an attr "data-remote=true", which in our ROR app makes it ajax. 我所做的就是检查href链接是否为“.js”,如果make_ajax为true,则添加attr“data-remote = true”,在我们的ROR应用程序中将其设为ajax。 if make_ajax is not true then am just removing the ".js" so the code does not mess. 如果make_ajax不是真的那么我只是删除“.js”所以代码不会乱。 I hope this helps 我希望这有帮助

Pierre Pretorius' answer is great, but I had to do a little more to make it work for me that wasn't already clear. 皮埃尔·普雷托里乌斯的答案很棒,但我必须多做一点才能让它对我起作用,这一点尚不清楚。 Maybe this will be helpful to other beginners. 也许这会对其他初学者有所帮助。

In addition to making that helper and using the js_will_paginate tag I did this: 除了制作帮助器并使用js_will_paginate标签之外,我还是这样做了:

After moving the content I was trying to paginate into a partial ( _recipes.html.erb in the case above), I also created a show.js.erb file (in this same view alongside the partial) with text similar to this: 移动我试图分页到部分(内容之后_recipes.html.erb在上面的情况下),我还创建一个show.js.erb文件(在沿着局部此相同的视图)具有类似于这样的文字:

$('#recipes').html('<%= escape_javascript(render partial: 'recipes') %>');

Then I had to move the js_will_paginate tag to the partial as well at the bottom (so it would be updated as I paginated through or clicked next/previous). 然后我不得不将js_will_paginate标记移动到部分以及底部(因此它会在我分页或点击下一个/上一个时更新)。 Then I had to wrap the render partial helper in the div id you're targeting in the js file, so in this example: 然后我不得不在你在js文件中定位的div id中包装渲染部分帮助器,所以在这个例子中:

<div id="recipes">
  <%= render partial: "recipes" %> 
</div>

This may have been very clear to others, but I wasn't sure which steps from the OP had to remain and which were unnecessary. 这可能对其他人来说非常清楚,但我不确定OP必须保留哪些步骤,哪些步骤是不必要的。 These steps worked for me. 这些步骤对我有用。 You don't need to add respond_to js in the controller as the helper takes care of that or have a coffeescript file. 您不需要在控制器中添加respond_to js,因为帮助程序负责处理或具有coffeescript文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM