jquery-ujs icon indicating copy to clipboard operation
jquery-ujs copied to clipboard

Changing ajax:complete delegation.

Open baxang opened this issue 11 years ago • 5 comments
trafficstars

Hi,

I have a remote form and want to leave the submit button disabled if the submission has succeeded while keep the original behaviour when failed.

I came up with loading this patch after jquery_ujs.js as https://github.com/rails/jquery-ujs/blob/master/src/rails.js#L460:L462 doesn't seem to allow me to override/change the default behaviour in a neat way :

(function($, undefined) {
  var $document = $(document);
  $document.undelegate($.rails.formSubmitSelector, 'ajax:complete.rails');
  $document.delegate($.rails.formSubmitSelector, 'ajax:error.rails', function(event) {
    if (this == event.target) $.rails.enableFormElements($(this));
  });
})(jQuery);

Is there a better way to do it? Otherwise it would be great if it's customizable.

baxang avatar Oct 27 '14 10:10 baxang

Have you tried to disable it again on the success callback? Sounds reasonable enough for me to do this in such case.

lucasmazza avatar Oct 27 '14 23:10 lucasmazza

Thank you for the suggestion @lucasmazza, but I think I can't rely on that because an ajax:complete is triggered after ajax:success or ajax:error events. The button still is disabled.

baxang avatar Oct 28 '14 04:10 baxang

@baxang It is customizable! The event binding is namespaced precisely so you can undelegate specific event bindings as needed, just as you've done here. So this is indeed a great way to do it. I'm not really sure what you have in mind in terms of overriding/changing behavior in a neat way.

As usual though there are other ways you could accomplish the same thing as well. You could do what @lucasmazza is suggesting by checking for success in the ajax:complete event:

$(document).delegate($.rails.formSubmitSelector, 'ajax:complete', function(event) {
  if (this == event.target && (status >= 200 && status < 300 || status === 304)) rails.disableFormElements($(this));
});

That takes your 5 lines down to 3 lines. Not sure if it's ideal or not, given that it would be enabled and then re-disabled quickly, or if it would even matter or be noticeable.

You could also try modifying the enableSelector or something like that, but I haven't really thought through how that could work for your situation.

JangoSteve avatar Oct 28 '14 05:10 JangoSteve

Thanks for the help. I'm glad to here my approach wasn't that bad. And I think your suggestion does the job too.

I've been thinking about what I ambiguously stated override/customize.

Just wrapping up my situation: I have a remote form that our website visitors can leave their contact information so we can call them later. The form uses ajax calls because I want to validate user input both the client and server-side without a page move. Once form submission has succeeded, the form's ajax:success callback executes location.href = data.path which has been returned from the server.

In this case re-enabling form elements after a successful request can confuse site visitors if the page move is not done as fast as the user cannot notice the delay and the user might try to submit the form again resulting duplications.

I was thinking if we can add a data-something option on form tag to control whether the form elements will be re-enabled or not per returned status(es). For instance <form data-enable-on="complete|error" ..>.

What do you think?

baxang avatar Oct 29 '14 02:10 baxang

:+1: for the approach from the comment above. We ran into the same problem. First we used a workaround:

$(this).find('button[type="submit"]').removeAttr('data-disable-with')

This code, added to the ajax:success callback, removes the data-disable-with attribute from the "Submit" button. As a result the button will remain disabled since $.rails.enableSelector query won't match it.

Later we decided to add a custom data-attribute that contains statuses (success, error) in which the submit button will be enabled on ajax:complete. It's similar to the mentioned above and I can open a pull request if you approve this solution.

arg avatar Dec 08 '14 08:12 arg