如何从 js.erb 触发 JS 函数作为 AJAX 调用的回调执行?
How do I trigger a JS function from a js.erb executed as a callback on an AJAX call?
我知道标题读起来有点古怪,但这就是我正在做的。
我有一个看起来像这样的 link,如我的 nodes_helper.rb
:
中所定义
link_to(favorite_node_path(node, node_counter: node_counter), class: "card-favorite-count favorited", method: :post, remote: true, data: {toggle_href: unfavorite_node_path(node) }) do
concat(content_tag(:i, "", class: "icon-heart"))
concat(node.cached_votes_total)
end
最终,如果成功,将导致 /views/nodes/favorites.js.erb
被执行:
$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');
一切正常,但我想做的是在按下 link 后向 class card-favorite-count
添加一些动画。基本上,就在计数更新之前。
我的动画在我的 app/assets/javascripts/nodes.js.coffee
中定义如下:
animate_favorite = ($favorite) ->
$favorite.addClass 'active'
card = $favorite.parent().parent().parent()
card_id = card.attr('id')
setTimeout (->
$('#' + card_id).find('.card-favorite-count').removeClass 'active'
return
), 1200
return
$(document).ready ->
$('.card-favorite-count').click ->
animate_favorite $(this)
return
return
上面的 JS 版本在普通的旧香草 HTML/JS 界面中工作,但我试图将它与我正在进行的所有其他事情联系起来 - 因此转换为 CoffeeScript。
那么,如何从我的 favorite.js.erb
中调用 animate_favorite
函数?
编辑 1
根据 Ryan 的建议,我在 favorite.js.erb
:
中尝试了这个
window.animate_favorite($(this));
$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');
但是我的 JS 控制台出现这个错误:
window.animate_favorite($(this));
$("#card-1 .card-attr").html('<a class="card-favorite-count favorited" data-method="post" data-remote="true" data-toggle-href="/nodes/2/favorite" href="/nodes/2/unfavorite?node_counter=1" rel="nofollow"><i class="icon-heart"></i>1</a>');
$("#card-1 .card-attr").append('<span class="card-comment-count"><i class="icon-speech-bubble-1"></i>0</span>');
comments.self.js?body=1:5 parsererror
编辑 2
根据 F 的问题,这是我用于此操作的控制器:
def favorite
@node.liked_by current_user
@node_counter = params[:node_counter]
current_user.events.create(action: "favorited", eventable: @node)
respond_to do |format|
format.js
format.html{ redirect_to @node }
end
end
编辑 3
当我按照 The F 的建议将我想要执行的 JS 直接放入我的 favorite.js.erb
时,一切都如我所愿。
即这是我的 favorite.js.erb
现在的样子:
$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');
$("#card-<%= @node_counter %> .card-attr .card-favorite-count").addClass('favorited active');
setTimeout(function() {
$("#card-<%= @node_counter %> .card-attr .card-favorite-count").removeClass('active');
},1200);
所以问题是,如何让它在我的 Rails JS 文件中工作?我应该把这个函数放在哪个文件中,这样我就可以在我的 favorite.js.erb
中执行它,而不是在那里声明它?
您需要将它们放在 window 命名空间中。在你的 nodes.js.coffee
文件中尝试这样的事情:
window.animate_favorite = ($favorite) ->
...code here...
然后,调用它(在您的 favorite.js.erb
文件中)所需要做的就是:
window.animate_favorite(...element you want to pass in...)
您是否在将节点插入 dom 之前调用 window.animate_favorite($('.card-favorite-count'));
?
更新答案
您最好 return 一个 json 响应,其中包含您想要包含和动画化的 html 部分。然后,您可以监听来自 nodes.js.coffee
的成功 ajax 调用,该调用是由收藏其中一张卡片触发的。为此,您应该研究如何有效地使用 javascript。也许看看 layouts & rendering and also passing data to javascript
目前我会保留代码原样,因为重复代码的数量相当少,而且它按您预期的方式工作。
favorite.js.erb
$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');
$("#card-<%= @node_counter %>").addClass('active');
setTimeout(function() { $("#card-<%= @node_counter %>").removeClass('active'); }, 1200);
此外,js 不是很一致,因为您在点击函数中传递 $('.card-favorite-count')
但想在 favorite.js.erb 中传递 $('i.icon-heart')
。您应该尝试始终使用相似的选择器(card
或 icon
),除非有特定的原因让您同时使用这两者。然而,坚持使用一个,也将简化您现有的 jquery.
我知道标题读起来有点古怪,但这就是我正在做的。
我有一个看起来像这样的 link,如我的 nodes_helper.rb
:
link_to(favorite_node_path(node, node_counter: node_counter), class: "card-favorite-count favorited", method: :post, remote: true, data: {toggle_href: unfavorite_node_path(node) }) do
concat(content_tag(:i, "", class: "icon-heart"))
concat(node.cached_votes_total)
end
最终,如果成功,将导致 /views/nodes/favorites.js.erb
被执行:
$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');
一切正常,但我想做的是在按下 link 后向 class card-favorite-count
添加一些动画。基本上,就在计数更新之前。
我的动画在我的 app/assets/javascripts/nodes.js.coffee
中定义如下:
animate_favorite = ($favorite) ->
$favorite.addClass 'active'
card = $favorite.parent().parent().parent()
card_id = card.attr('id')
setTimeout (->
$('#' + card_id).find('.card-favorite-count').removeClass 'active'
return
), 1200
return
$(document).ready ->
$('.card-favorite-count').click ->
animate_favorite $(this)
return
return
上面的 JS 版本在普通的旧香草 HTML/JS 界面中工作,但我试图将它与我正在进行的所有其他事情联系起来 - 因此转换为 CoffeeScript。
那么,如何从我的 favorite.js.erb
中调用 animate_favorite
函数?
编辑 1
根据 Ryan 的建议,我在 favorite.js.erb
:
window.animate_favorite($(this));
$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');
但是我的 JS 控制台出现这个错误:
window.animate_favorite($(this));
$("#card-1 .card-attr").html('<a class="card-favorite-count favorited" data-method="post" data-remote="true" data-toggle-href="/nodes/2/favorite" href="/nodes/2/unfavorite?node_counter=1" rel="nofollow"><i class="icon-heart"></i>1</a>');
$("#card-1 .card-attr").append('<span class="card-comment-count"><i class="icon-speech-bubble-1"></i>0</span>');
comments.self.js?body=1:5 parsererror
编辑 2
根据 F 的问题,这是我用于此操作的控制器:
def favorite
@node.liked_by current_user
@node_counter = params[:node_counter]
current_user.events.create(action: "favorited", eventable: @node)
respond_to do |format|
format.js
format.html{ redirect_to @node }
end
end
编辑 3
当我按照 The F 的建议将我想要执行的 JS 直接放入我的 favorite.js.erb
时,一切都如我所愿。
即这是我的 favorite.js.erb
现在的样子:
$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');
$("#card-<%= @node_counter %> .card-attr .card-favorite-count").addClass('favorited active');
setTimeout(function() {
$("#card-<%= @node_counter %> .card-attr .card-favorite-count").removeClass('active');
},1200);
所以问题是,如何让它在我的 Rails JS 文件中工作?我应该把这个函数放在哪个文件中,这样我就可以在我的 favorite.js.erb
中执行它,而不是在那里声明它?
您需要将它们放在 window 命名空间中。在你的 nodes.js.coffee
文件中尝试这样的事情:
window.animate_favorite = ($favorite) ->
...code here...
然后,调用它(在您的 favorite.js.erb
文件中)所需要做的就是:
window.animate_favorite(...element you want to pass in...)
您是否在将节点插入 dom 之前调用 window.animate_favorite($('.card-favorite-count'));
?
更新答案
您最好 return 一个 json 响应,其中包含您想要包含和动画化的 html 部分。然后,您可以监听来自 nodes.js.coffee
的成功 ajax 调用,该调用是由收藏其中一张卡片触发的。为此,您应该研究如何有效地使用 javascript。也许看看 layouts & rendering and also passing data to javascript
目前我会保留代码原样,因为重复代码的数量相当少,而且它按您预期的方式工作。
favorite.js.erb
$("#card-<%= @node_counter %> .card-attr").html('<%= favorites_count(@node, @node_counter) %>');
$("#card-<%= @node_counter %> .card-attr").append('<%= comments_count(@node) %>');
$("#card-<%= @node_counter %>").addClass('active');
setTimeout(function() { $("#card-<%= @node_counter %>").removeClass('active'); }, 1200);
此外,js 不是很一致,因为您在点击函数中传递 $('.card-favorite-count')
但想在 favorite.js.erb 中传递 $('i.icon-heart')
。您应该尝试始终使用相似的选择器(card
或 icon
),除非有特定的原因让您同时使用这两者。然而,坚持使用一个,也将简化您现有的 jquery.