【问题标题】:AJAX to update micropost vote up/down partial only refreshes the most recent postAJAX 更新微博投票上/下部分只刷新最近的帖子
【发布时间】:2015-08-12 16:33:47
【问题描述】:

使用 Rails 3、JRuby。

我想为我的 Rails 社交应用程序加入“赞成”和“反对”评级,让用户基本上可以喜欢和不喜欢帖子。这效果很好,但是每当对帖子进行投票时都会刷新整个页面。为了解决这个问题,我想在帖子提要中实现仅更新特定帖子分数的部分刷新。

我按照我通常的模式来实现 AJAX 部分刷新,但是,结果并不完全符合我的想法。它不会刷新我喜欢/不喜欢的帖子,而是使用我刚刚喜欢/不喜欢的帖子的新分数刷新最近的帖子。

我已将此确定为部分刷新问题,因为当我手动刷新整个页面时,每个帖子都有正确的喜欢/不喜欢分数(包括我打算更改的那个)。我相信问题与我的页面使用“do block”将帖子呈现到页面的方式有关。我的问题是,我无法弄清楚如何获得正确刷新我投票的微博的期望行为。这是我的一些代码:

_micropost.html.erb(部分)

<% microposts.each do |mp| %>
<div class="profile_block gradient ">
    <!-- Header -->
    <header class="top-bar">
        <small class="badge sharp">Post</small>
        <!-- post/ article options -->
        <% if mp.user_id == current_user.id %>       
          <%= link_to '<span class="glyphicon glyphicon glyphicon-cog"></span>'.html_safe, '#', class: "comment_link pull-right"%>
        <% end %>

        <%= link_to '<span class="glyphicon glyphicon glyphicon-heart"></span>'.html_safe, increment_micropost_path(mp.id), class: "comment_link pull-right", :remote => true%>

        <%= link_to '<span class="glyphicon glyphicon glyphicon-thumbs-down"></span>'.html_safe, decrement_micropost_path(mp.id), class: "comment_link pull-right", :remote => true %>

        <div id="global" class="pull-right badge"><%= render :partial => 'microposts/rating', :locals => {:micro => mp} %></div>
    </header> 
(....)
<% end %>
</div>

_home.html.erb

(....)
<div id="gf" class="left_col">          
    <%= render :partial => 'microposts/micropost', :locals => {:microposts => @microposts }, :remote => true %>
</div>
(....)

我的 _rating.html.erb 部分(显示信息的位)

<%= micro.rating.to_i %>

控制器(我只显示增量方法,它们几乎相同

#increments micropost rating by 1
def increment
    @micropost = Micropost.find(params[:id])
    @increment = lambda { |micropost| micropost.update_attribute(:rating, micropost.rating.to_i + 1) }
    @increment.call @micropost
    respond_to do |format|
        format.html {redirect_to root_url}
        format.js
    end
end

以及对应的increment.js.html

$('#global').html("<%= escape_javascript render :partial => 'microposts/rating', :locals => {:micro => @micropost} %>"); 

我在上面提到过,micropost 的实际递增/递减功能可以正常工作 - 它只是使用 AJAX 重新呈现此信息,而其行为与预期不符。 任何想法,请分享。

【问题讨论】:

    标签: javascript jquery ruby-on-rails ajax partial-views


    【解决方案1】:

    原因是你的代码中有多个div#global(因为each 循环),所以浏览器只会识别第一个。将 global 从一个 id 更改为一个类,然后它应该可以工作。我还将向div 添加一个data-num 属性并将其分配给数据库对象的id(不要与HTML id 混淆)。像这样的:

    <div class="pull-right badge global" data-num="<%= mp.id %>"><%= render :partial => 'microposts/rating', :locals => {:micro => mp} %></div>
    

    然后,在您的 increment.js.erb(我认为您的意思是,而不是 .js.html...)中,将其更改为:

    $('div.global[data-num="<%= @micropost.id %>"]').html("<%= escape_javascript render :partial => 'microposts/rating', :locals => {:micro => @micropost} %>");
    

    这样,JavaScript 将始终知道要更新哪一个,因为它基于数据库 ID。

    【讨论】:

    • 有效! - 从来不知道您可以为 div 分配一个与对象 id 对应的数据编号,这在动态生成多个 div 时是有意义的。希望其他人发现这和我一样有用。
    • 是的。任何以data-为前缀的元素上的任何属性都将被浏览器本身忽略,并且通常由JavaScript使用。例如,如果您希望在单击特定链接时出现确认框,只需在链接中添加data-confirm="Are you sure?",JavaScript 就会自动显示该框。
    猜你喜欢
    • 2018-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多