ajax:success和ajax:在Rails中使用UJS时,完全回调不起作用

时间:2022-04-05 12:57:47

I have a link that when i click on it will trigger an ajax call then replace this link by another link, says for example the original link is "add friend", when i click this link it will send an ajax request to add_friend action then if the friend is added the link above will be replaced by another link "cancel request", i use ujs for that :

我有一个链接,当我点击它将触发ajax调用然后用另一个链接替换此链接,例如说原始链接是“添加朋友”,当我点击此链接它将发送ajax请求add_friend行动然后如果添加好友,上面的链接将被另一个链接“取消请求”替换,我使用ujs:

$("#link_for_friend").html("<%= escape_javascript(render('users/cancel_link')) %>")

when i try to add callback (:success and :complete) it doesn't works, i tried with :beforeSend like the following it works :

当我尝试添加回调(:成功和:完成)时,它不起作用,我尝试使用:beforeSend,如下所示:

$(document).ready ->
  $("#my_link").on "ajax:beforeSend", ->
    alert("hello")

there is a solution for success and complete callback ?

有成功和完全回调的解决方案吗?

note : my idea is to show an loader.gif when ajaxStart is triggered then hide it when ajax:complete callback is triggered at least , also if there is some error i want to show it when ajax:error is triggered

注意:我的想法是在ajaxStart被触发时显示loader.gif然后在ajax:至少触发完全回调时隐藏它,如果有一些错误我想在ajax:error被触发时显示它

Update

I tried to solve this by moving the code inside action.js.erb to js file like this :

我试图通过将action.js.erb中的代码移动到js文件来解决这个问题,如下所示:

  $(document).ready ->
  $(document).on("ajax:success", "a.invitation-box", ->
    $("#link_for_friend").html("<%= escape_javascript(render('users/cancel_link')) %>")
  ).on "ajax:error", "a.invitation-box", ->
    alert "error"

but this way its not possible to put render('users/cancel_link') inside a JS file

但这样就不可能将render('users / cancel_link')放在JS文件中

4 个解决方案

#1


5  

I had the same issue, and the problem is not with ajax:success or ajax:complete callback. The problem is that when displaying the loading gif image, you replace the content of the container, including the link itself. So the element on which you apply the success, complete callback is not part of the DOM anymore, that's why the callback is not fired.

我有同样的问题,问题不在于ajax:success或ajax:完全回调。问题是,在显示加载gif图像时,您将替换容器的内容,包括链接本身。因此,应用成功的元素,完整的回调不再是DOM的一部分,这就是为什么不触发回调的原因。

One solution would be to hide the element and append the loading image, like following:

一种解决方案是隐藏元素并附加加载图像,如下所示:

$('#my_link').on "ajax:send", (event, xhr, settings) ->
        $('#my_link').hide()
        $("#my_link_container").append("<image src = 'img.gif' />")

Then the success and complete callback will be fired. Hope it helps somebody :)

然后将触发成功和完整回调。希望它有助于某人:)

#2


3  

I believe your problem is down to JS not being able to bind to your object, as it's been changed. The way JS works is to "bind" / "attach" itself to elements in the DOM (Document Object Model). The DOM is basically a huge list of elements JS uses to call certain functions, and thus allows you to allocate various functions to those elements. That's how you can call "click" functions on different elements.

我相信你的问题归结为JS无法绑定到你的对象,因为它已被更改。 JS的工作方式是将自己“绑定”/“附加”到DOM(文档对象模型)中的元素。 DOM基本上是JS用于调用某些函数的巨大元素列表,因此允许您为这些元素分配各种函数。这就是你可以在不同的元素上调用“点击”功能的方法。

You're basically replacing the object that you've called the Ajax from, so when 'ajax:success' happens, JS has no way to know which object to associate it with, thus preventing the function from firing

你基本上是替换了你调用Ajax的对象,所以当'ajax:success'发生时,JS无法知道将它关联到哪个对象,从而阻止了函数的触发

The way to get around this is to bind to the document, and then delegate the bind to your div, like this:

解决这个问题的方法是绑定到文档,然后将绑定委托给div,如下所示:

$(document).on 'ajax:success' , '#my_link', ->
  //do stuff here

This means that even if this element changes dynamically, it will still have the function bound to it, thus giving you what you need :)

这意味着即使这个元素动态变化,它仍然会绑定它的函数,从而为您提供所需的内容:)

#3


1  

I met this problem before, UJS's ajax:success and ajax:complete won't be fired. But other callbacks work, such as ajax:beforeSend

我之前遇到过这个问题,UJS的ajax:成功和ajax:完成不会被解雇。但其他回调也有效,例如ajax:beforeSend

My fix is to use jQuery's global event callback to handle it

我的修复是使用jQuery的全局事件回调来处理它

$("#my_link").on('ajaxComplete', (evt, data, status, xhr) ->
  alert('This is a jQuery ajax complete event!')

P.S. UJS use jQuery's ajax to send Ajax, so jQuery's callback will surely be fired.

附: UJS使用jQuery的ajax发送Ajax,因此jQuery的回调肯定会被解雇。

# https://github.com/rails/jquery-ujs/blob/master/src/rails.js
ajax: function(options) {
  return $.ajax(options);
},

#4


1  

Try this in your action.js.erb:

在action.js.erb中试试这个:

setTimeout(function () {
  ("#link_for_friend").html("<%= escape_javascript(render('users/cancel_link')) %>")
});

This will put the html replacement to the next timer tick that happens after the ajax:* events being triggered.

这将把html替换放到触发ajax:*事件后发生的下一个计时器滴答。

#1


5  

I had the same issue, and the problem is not with ajax:success or ajax:complete callback. The problem is that when displaying the loading gif image, you replace the content of the container, including the link itself. So the element on which you apply the success, complete callback is not part of the DOM anymore, that's why the callback is not fired.

我有同样的问题,问题不在于ajax:success或ajax:完全回调。问题是,在显示加载gif图像时,您将替换容器的内容,包括链接本身。因此,应用成功的元素,完整的回调不再是DOM的一部分,这就是为什么不触发回调的原因。

One solution would be to hide the element and append the loading image, like following:

一种解决方案是隐藏元素并附加加载图像,如下所示:

$('#my_link').on "ajax:send", (event, xhr, settings) ->
        $('#my_link').hide()
        $("#my_link_container").append("<image src = 'img.gif' />")

Then the success and complete callback will be fired. Hope it helps somebody :)

然后将触发成功和完整回调。希望它有助于某人:)

#2


3  

I believe your problem is down to JS not being able to bind to your object, as it's been changed. The way JS works is to "bind" / "attach" itself to elements in the DOM (Document Object Model). The DOM is basically a huge list of elements JS uses to call certain functions, and thus allows you to allocate various functions to those elements. That's how you can call "click" functions on different elements.

我相信你的问题归结为JS无法绑定到你的对象,因为它已被更改。 JS的工作方式是将自己“绑定”/“附加”到DOM(文档对象模型)中的元素。 DOM基本上是JS用于调用某些函数的巨大元素列表,因此允许您为这些元素分配各种函数。这就是你可以在不同的元素上调用“点击”功能的方法。

You're basically replacing the object that you've called the Ajax from, so when 'ajax:success' happens, JS has no way to know which object to associate it with, thus preventing the function from firing

你基本上是替换了你调用Ajax的对象,所以当'ajax:success'发生时,JS无法知道将它关联到哪个对象,从而阻止了函数的触发

The way to get around this is to bind to the document, and then delegate the bind to your div, like this:

解决这个问题的方法是绑定到文档,然后将绑定委托给div,如下所示:

$(document).on 'ajax:success' , '#my_link', ->
  //do stuff here

This means that even if this element changes dynamically, it will still have the function bound to it, thus giving you what you need :)

这意味着即使这个元素动态变化,它仍然会绑定它的函数,从而为您提供所需的内容:)

#3


1  

I met this problem before, UJS's ajax:success and ajax:complete won't be fired. But other callbacks work, such as ajax:beforeSend

我之前遇到过这个问题,UJS的ajax:成功和ajax:完成不会被解雇。但其他回调也有效,例如ajax:beforeSend

My fix is to use jQuery's global event callback to handle it

我的修复是使用jQuery的全局事件回调来处理它

$("#my_link").on('ajaxComplete', (evt, data, status, xhr) ->
  alert('This is a jQuery ajax complete event!')

P.S. UJS use jQuery's ajax to send Ajax, so jQuery's callback will surely be fired.

附: UJS使用jQuery的ajax发送Ajax,因此jQuery的回调肯定会被解雇。

# https://github.com/rails/jquery-ujs/blob/master/src/rails.js
ajax: function(options) {
  return $.ajax(options);
},

#4


1  

Try this in your action.js.erb:

在action.js.erb中试试这个:

setTimeout(function () {
  ("#link_for_friend").html("<%= escape_javascript(render('users/cancel_link')) %>")
});

This will put the html replacement to the next timer tick that happens after the ajax:* events being triggered.

这将把html替换放到触发ajax:*事件后发生的下一个计时器滴答。