【问题标题】:How can I update an instance variable with each ajax request?如何使用每个 ajax 请求更新实例变量?
【发布时间】:2015-04-16 06:49:50
【问题描述】:

我在模型Page 的视图上有一长块cmets。我没有在页面加载时显示所有 cmets,而是尝试创建一个“查看更多”按钮来显示接下来的十个 cmets。按钮向控制器发送一个 ajax 请求,然后控制器使用 jquery 呈现这个块:

_view_more.html.erb

<% comments.each_with_index do |comment, index|%>
  <% if (( index > @start_number) && (index < @end_number) ) %>
  <%= comment.text %>
<% end %>

假设我总是想显示接下来的 10 个 cmets。我会设置@start_number = @start_number + 10@end_number = @end_number + 10 在控制器中,但实例变量被重置,所以@start_number 将为零。如何设置一个在每次 ajax 请求时增加 10 的变量?

“查看更多”按钮

<%= link_to "view more", view_more_page_path, remote: true %>

pages_controller.rb

def view_more
  @page = Page.find(params[:id])
  respond_to do |format|
    format.html { redirect_to root_path }
    format.js
  end
end

view_more

$("#comments-body").append("<%= escape_javascript(render 'view_more') %>");

【问题讨论】:

  • 我知道这并不能回答您的问题,但是您确定您不想只在客户端跟踪并使用 ajax 发送开始和(如有必要)结束索引请求?
  • @JMM 我没有考虑过。我怎么能这样做?

标签: javascript jquery ruby-on-rails ajax instance-variables


【解决方案1】:

我将使用hamlcoffee-script

在渲染comments 时,您将html5 data attributeidid 放在一起:

#view where to render comments
%div#comments-wrapper{:"data-pageid" => @page.id}
  =render @comments
=link_to "View more", "#", id: "view-more-link"

评论部分

#comments/_comment.html.haml
%p.single-comment{:"data-commentid" => comment.id}
  =comment.body

application.coffee

$ ->
  $("#view-more-link").on 'click', ->
    last_comment_id = $("#comments-wrapper .single-comment").last().data('commentid')
    page_id = $("#comments-wrapper").data("pageid")
    $.ajax
      url: "/comments/view_more"
      dataType: "script"
      data:
        last_comment_id: last_comment_id
        page_id: page_id

cmets_controller

def view_more
  @page = Page.find(params[:pageid])
  if params[:last_comment_id]
    @comments = @page.comments.where("comments.id > ?", params[:last_comment_id]).limit(10)
  end
  respond_to do |format|
    format.js
  end
end

cmets/view_more.js.erb

$("#comments-wrapper").append("<%= escape_javascript(render @comments) %>");

注意:我不知道您的路线是如何设置的,因此我也将 page.id 作为数据属性

【讨论】:

    【解决方案2】:

    我会使用已经实现的分页 gem kaminariwill_paginate。我将使用 will_paginate 创建这个示例。

    首先,重要的是要说您的方法不正确,因为它会加载所有 cmets 每个view_more 请求。如果你想显示 10 个 cmets,只从数据库中选择它们是有意义的,对吧?分页宝石将为您完成!

    让我们来看看代码:

    “查看更多”按钮

    <%= link_to "view more", view_more_page_path, remote: true, id: 'view-more-btn' %>
    

    pages_controller.rb

    def view_more
      @comments = Page.find(params[:id]).comments.paginate(page: params[:page], per_page: 10)
      respond_to do |format|
        format.html { redirect_to root_path }
        format.js
      end
    end
    

    _view_more.html.erb

    <% @comments.each do |comment| %>
      <%= comment.text %>
    <% end %>
    

    view_more.js.erb

    $("#comments-wrapper").append("<%= escape_javascript(render 'view_more') %>");
    # We need to update the 'view more' link with the next page number
    $('#view-more-btn').attr('href', '<%= view_more_page_path((params[:page] || 0) + 1) %>')
    

    【讨论】:

    • 代码真的足够了吗?实际工作起来似乎太简单了。
    • 例如,如何选择每页返回多少条记录?
    • @JoeMorano,您需要安装 de will_paginate gem
    • 按下按钮时没有任何反应。我是否需要在某处需要一个文件才能使 gem 工作?
    • 没有@JoeMorano。 AJAX 请求是在你按下按钮时发出的?
    【解决方案3】:

    在使用计数进行 ajax 调用之前更新隐藏变量不是很好吗?

    var currentVal = parseInt($("[type=hidden]").val());
    $("[type=hidden]").val( currentVal + 1 );
    

    在 cmets 部分的开头添加隐藏字段,默认值为“0”

    <input type="hidden" name="hiddenId" id="hiddenId" value="0">
    

    希望对你有帮助

    【讨论】:

      【解决方案4】:

      如果您想要一种快速而肮脏的方法,您可以将 start_number 和 end_number 保存在 cookie 中。

      但是跟踪客户端接下来需要渲染的内容是正确的做法。

      【讨论】:

        猜你喜欢
        • 2019-06-09
        • 2021-06-27
        • 2019-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-10
        • 2018-06-23
        • 1970-01-01
        相关资源
        最近更新 更多