Rails-Ajax无法正确刷新

时间:2019-01-15 09:15:30

标签: ruby-on-rails ajax

在我的应用中,用户可以将产品标记为收藏,然后取消标记。

我希望当用户喜欢产品时,图标颜色会改变,并且喜欢的计数器会在不重新加载的情况下增加。

计数器在导航栏中

<%= @favorites.count %>

这是 products / indx.html.erb

<% @products.each do |product| %>
    <div class="header_card">
        <%= link_to clients_product_path(product) do  %>
        <div id="like_unlike">
            <% if product.favoriting_users.include? current_user %>
                <% fav = product.favorites.find { |fav| fav.user_id == current_user.id} %>
                <%= link_to clients_product_favorite_path(product, fav), method: :delete , remote: true do %>
                    <i class= "fa fa-heart favorite-active"></i>
                <% end %>       
            <% else %>
                <%= link_to clients_product_favorites_path(product), method: :post, remote: true  do %>
                    <i class= "fa fa-heart not-favorite"></i>
                <% end %>
            <% end %>   
        </div>
        <div id="carousel_<%= product.id%>" class="carousel slide" data-ride="carousel" data-interval="false">
          <div class="carousel-inner">
              <% product.attachments.each do |img| %>
              <div class="carousel-item <%= 'active' if img == product.attachments[0] %>">  
                <%= image_tag img.url,  class: "product_suggestion"  %>                                     
              </div>
                <% end %>
          </div>
        </div>
        <% end %>
    </div>
<% end %>

这是我的 favorites_controller.rb

class Clients::FavoritesController < ApplicationController

    before_action :find_favorite, only: [:destroy]

    def index
        @favorites = Favorite.where(user: current_user).all
    end

    def create
      @product = Product.find(params[:product_id])
      @user = current_user.id
      favorites = {user_id: @user, product_id: @product.id}
      @favorite = Favorite.new(favorites)

      @favorite.save

        if @favorite.save
        respond_to do |format|
            format.js
            format.html {redirect_to clients_products_path(@product)}
          end
        else
            respond_to do | format|
                format.js 
                format.html {redirect_to clients_products_path,  alert: "HOPHOP" }
            end
        end
    end

    def destroy 
        if @favorite.destroy!
            respond_to do |format|
                format.js 
            end
        end
    end

    private

    def find_favorite
        find_product
       @favorite = @product.favorites.find(params[:id])
    end
end

编辑

试图使问题更清晰...

这个想法是,当喜欢某个产品时,应该增加收藏夹计数器<%= @favorites.count %>而不进行重新加载。 当不再喜欢时,计数器应递减

我有两个图标,根据是否喜欢,只有一个可见。

我的产品/index.html.erb中的

我有这些行(上面的完整代码)

当尚不喜欢某个产品时,将显示此图标:

<%= link_to clients_product_favorites_path(product), method: :post, remote: true  do %>
  <i class= "fa fa-heart not-favorite"></i>
<% end %> 

喜欢该图标时,该图标应重新加载...

<% fav = product.favorites.find { |fav| fav.user_id == current_user.id} %>
<%= link_to clients_product_favorite_path(product, fav), method: :delete , remote: true do %>
  <i class= "fa fa-heart favorite-active"></i>
<% end %>   

是否可以在create.js.erb中传递一些rails代码,然后将方法post的link_to更改为方法delete的链接

create.js.erb *在这里,我只是通过更改css来伪造图标更改。...这是我的hack,但是我需要检索可以使用delete方法的其他图标_

$('.header_card').bind('.not-favorite').bind('ajax:success', function(){
        $(this).find(".not-favorite").css('color', 'red');
        $("#likes_counter").html("<%= @favorites.count %>");
});

destroy.js.erb 与以下相同

$('.header_card').bind('.favorite-active').bind('ajax:success', function(){
    $("#likes-count").html("<%= @favorites.count %>");
    $(this).find(".favorite-active").css('color', 'gray');
});

2 个答案:

答案 0 :(得分:2)

首先,我建议您像这样简化控制器:

def create
  @product = Product.find(params[:product_id])
  @favorite = current_user.favorites.create(product: @product) #I guess you have that association already set up

  respond_to do |format|
    format.js
    format.html {
      if @favorite.persisted?
        redirect_to clients_products_path(@product)
      else
        redirect_to clients_products_path,  alert: "HOPHOP"
      }
  end
end

只是减少可能出错的行数。

在视图上,不必将回调函数绑定到ajax:success事件,在呈现该视图的上下文中,您已经在该事件内。只需添加代码行来更新视图,jQuery将执行它们。

# create.js.erb
$('.header_card .not-favorite').toggleClass('not-favorite').toggleClass('favorite-active');
$("#likes_counter").html("<%= @product.favorites.count %>");

# destroy.js.erb
$('.header_card .favorite-active').toggleClass('not-favorite').toggleClass('favorite-active');
$("#likes-count").html("<%= @product.favorites.count %>");

请注意类的更改(您可以使用CSS设置图标,然后只需要在按钮上设置propper类即可完成)和计数(您在未定义的地方使用@favorites)在控制器上)。

答案 1 :(得分:0)

这是按预期完成工作的原因:

我首先使用#id将链接放入div

<div class="like_unlike">
  <% if product.favoriting_users.include? current_user %>
   <div id="unlike_<%= product.id %>">
    <% fav = product.favorites.find { |fav| fav.user_id == current_user.id} %>
      <%= link_to clients_product_favorite_path(product, fav), method: :delete , remote: true do %>
        <i class= "fa fa-heart favorite-active"></i>
    <% end %>   
   </div>   
 <% else %>
    <div id="like_<%= product.id %>">
      <%= link_to clients_product_favorites_path(product), method: :post, remote: true  do %>
        <i class= "fa fa-heart not-favorite"></i>
    <% end %>
 </div>
<% end %>   

create.js.erb

$('#header_card_<%= @product.id %>').bind('.not-favorite').bind('ajax:success', function(){

    if("<%= @favorites.count %>" === "1"){
            $("#like_<%= @product.id %>").empty();
            $("#header_card_<%= @product.id %>").find("#like_<%= @product.id %>").replaceWith("<div class='unlike_<%= @product.id %>'><a data-remote='true' rel='nofollow' data-method='delete' href='/clients/products/<%= @product.id %>/favorites/<%= @favorite.id %>'><i class= 'fa fa-heart favorite-active'></i></a></div>"); 
            $("#header_card_<%= @product.id %> .not-favorite").toggleClass('not-favorite').toggleClass('favorite-active');
            $("#likes_counter").html("<%= @favorites.count %>");
        location.reload();  
    }
    else {
        $("#like_<%= @product.id %>").empty();
        $("#header_card_<%= @product.id %>").find("#like_<%= @product.id %>").replaceWith("<div class='unlike_<%= @product.id %>'><a data-remote='true' rel='nofollow' data-method='delete' href='/clients/products/<%= @product.id %>/favorites/<%= @favorite.id %>'><i class= 'fa fa-heart favorite-active'></i></a></div>"); 
        $("#header_card_<%= @product.id %> .not-favorite").toggleClass('not-favorite').toggleClass('favorite-active');
        $("#likes_counter").html("<%= @favorites.count %>");
    }
});

destroy.js.erb

$('#header_card_<%= @product.id %>').bind('.not-favorite').bind('ajax:success', function(){ 
    if('<%= @favorites.count %>' === "0" || "<%= @favorites.first %>"){
        $("#likes_counter").html("<%= @favorites.count %>");
      $("#header_card_<%= @product.id %> .favorite-active").toggleClass('favorite-active').toggleClass('not-favorite');
        $("#unlike_<%= @product.id %>").empty();
        $("#header_card_<%= @product.id %>").find("#unlike_<%= @product.id %>").replaceWith("<div class='like_<%= @product.id %>'><a data-remote='true' rel='nofollow' data-method='post' href='/clients/products/<%= @product.id %>/favorites %>'><i class= 'fa fa-heart favorite-active'></i></a></div>");
        location.reload();
    }
    else {
        $("#likes_counter").html("<%= @favorites.count %>");
      $("#header_card_<%= @product.id %> .favorite-active").toggleClass('favorite-active').toggleClass('not-favorite');
        $("#unlike_<%= @product.id %>").empty();
        $("#header_card_<%= @product.id %>").find("#unlike_<%= @product.id %>").replaceWith("<div class='like_<%= @product.id %>'><a data-remote='true' rel='nofollow' data-method='post' href='/clients/products/<%= @product.id %>/favorites %>'><i class= 'fa fa-heart favorite-active'></i></a></div>");
    }
});