19

I'm using Rails UJS. I have a form setup to do a remote submit like so:

<form accept-charset="UTF-8" action="/subscriptions" class="new_subscription form-horizontal" id="new_subscription" data-remote="true" data-type="json" method="POST">

I'm trying to find a way to submit this form from a JavaScript function. I've tried:

var form$ = $("#new_subscription");
form$.get(0).submit();

but the problem with this is that it submits the form w/o the remote, it posts to the server and refreshes the page. Any idea why that is? Is there a different way to submit a remote form?

Thanks

AnApprentice
  • 108,152
  • 195
  • 629
  • 1,012

3 Answers3

44

Perhaps for those using jquery-ujs (Rails 5.0 default and below), as Mikhail as already answered, triggering the custom jquery event will work, i.e.:

$("#new_subscription").trigger("submit.rails");

For those who have stumbled upon this question in 2017 and is using Rails 5.1, the answer will be different. Rails 5.1 has dropped jquery as a dependency and therefore has replaced jquery-ujs with a complete rewritten rails-ujs. See: http://weblog.rubyonrails.org/2017/4/27/Rails-5-1-final/

As such, you'll have to trigger the proper CustomEvent object in rails-ujs:

As of the moment, there's no published/recommended way of doing it in the documentation (a.k.a. RailsGuides), but here are a number of options that you could use just by looking at Rails' source code:

  1. Use Rails.fire function:

    nativeFormEl = $("#new_subscription")[0] // you need the native DOM element
    Rails.fire(nativeFormEl, 'submit')
    
  2. You could also programmatically call the Rails.handleRemote handler (the one that actually submits forms with data-remote=true via XHR:

    nativeFormEl = $("#new_subscription")[0] // you need the native DOM element
    Rails.handleRemote.call(nativeFormEl, event); // unfortunately, you cannot reference the previously created submit CustomEvent object by rails-ujs.js
    //  ... or ...
    Rails.handleRemote.call(nativeFormEl) // submits via XHR successfully, but throws an error after success callback at Rails.stopPropagation
    

I prefer Option 1 because it's just a wrapper that uses more recent Web API methods i.e. creating a CustomEvent and dispatches it to the EventTarget via dispatchEvent.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
padi
  • 787
  • 7
  • 11
  • 1
    Option 1 is the real unswer for rails 5! Thanks! Works like a charm. – Brazhnyk Yuriy Mar 18 '18 at 22:27
  • 1
    Can also confirm Option 1 works great, however to access the `Rails` object while using webpacker you'll need to do `import Rails from '@rails/ujs'; Rails.start()` first. See https://stackoverflow.com/questions/56128114/using-rails-ujs-in-js-modules-rails-6-with-webpacker – Paul Odeon Feb 20 '20 at 12:25
  • Wanted to add that I am currently using the following in my code: `Rails.fire(nativeFormEl, 'ajax:success')` -- and while this does trigger the `ajax:success` event, it passes in the _wrong/old_ class of `CustomEvent` that Rails UJS uses. The new `CustomEvent` class has a 3 item array at the key `event.details` but the old format does not. It's confusing and I had to write a silly if-then statement as a workaround to properly process code in my Ajax event listener – FireDragon Feb 25 '20 at 22:37
15

Try to trigger the submit.rails event:

$("#new_subscription").trigger("submit.rails");
Mik
  • 4,117
  • 1
  • 25
  • 32
  • 12
    While this is probably the correct answer a few years ago, this is not true anymore. Since Rails 5.1 replaced jquery-ujs with rails-ujs, the jQuery dependency has been removed and the custom events have changed. I've stumbled upon your answer only to verify that this is not the answer anymore. Will post anew once I've verified the most recent answer. – padi Jul 06 '17 at 08:57
-1

Try doing an Ajax request by yourself:

$('#new_suscription').submit(function(){
  /*do whatever you want here*/
  $.post('/subscriptions',$(this).serialize(),function(){},'script');
}

That way, you do a POST request with the form data and execute the response as a script.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
arieljuod
  • 15,460
  • 2
  • 25
  • 36