ajax:success and ajax:complete callback doesn't work when using UJS in Rails

南笙酒味 提交于 2019-12-01 04:16: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 :

$("#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 :

$(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

Update

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

  $(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


回答1:


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.

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:


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.

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

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

$(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:


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

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

$("#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.

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



回答4:


Try this in your 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.



来源:https://stackoverflow.com/questions/19384720/ajaxsuccess-and-ajaxcomplete-callback-doesnt-work-when-using-ujs-in-rails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!