Search code examples
javascriptjqueryruby-on-railsajaxujs

Remote modal form in rails, not triggering AJAX events


I have created a modal form in Rails, that submits values remotely using AJAX.

For some reason, submission of the modal form itself, does not trigger any AJAX events. If I add the exact same form code in the page (i.e. not on a modal), it triggers the AJAX events when submitted.

Here is my code:

//index.haml
= link_to 'New', new_foo_path, data: { remote: true, type: 'script'}

//_form.haml
= bootstrap_form_for @foo, remote: true do |f|  
  = f.text_field :bar
  = f.button "Save"


//foos_controller.rb
def create
  respond_to do |format|
    if @foo.save
      format.json { render json: @foo, status: :ok }
    else
      format.json { render json: @foo.errors, status: :unprocessable_entity }
    end
  end
end

//foo.coffee
$('#new_foo').on('ajax:success', (e, data, status, xhr) ->
  console.log 'Great success'
).on 'ajax:error', (e, data, status, xhr) ->
  console.log 'Great failure'

Using the code given above, lets me see a 422 error when submitting the form with values that does not pass validation. This behaviour is expected. This does however not print the above messages to the Chrome Dev Console log. If I add the form code to the index view itself and submit it from there, I can see a 422 error as well as the log messages assigned in 'foo.coffee'.

Can anybody spot something that I'm missing?


Solution

  • After re-looking into your code, I figure what the actual issue could be. You modal form is loaded using JS, that means when your page loads in browser it is absent. And that's why the JS you have didn't/couldn't bind the callback code to the form, because the source Dom where you want to bind/register it doesn't exist. To solve the issue, you need to register the callback to an element which exists in the page when it loads firs time and your form has to be its one of the children. This concept is called Event Delegation. So the below code will work:

    $('body')
    .on 'ajax:success', '#new_foo', (e, data, status, xhr) ->
      console.log 'Great success'
    .on 'ajax:error', '#new_foo', (e, data, status, xhr) ->
      console.log 'Great failure'