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

后端 未结 4 527
醉梦人生
醉梦人生 2021-01-13 15:43

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 th

相关标签:
4条回答
  • 2021-01-13 16:20

    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 :)

    0 讨论(0)
  • 2021-01-13 16:21

    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);
    },
    
    0 讨论(0)
  • 2021-01-13 16:21

    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.

    0 讨论(0)
  • 2021-01-13 16:25

    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 :)

    0 讨论(0)
提交回复
热议问题