jqueryruby-on-railsrjs

How do I submit a from from a .js.erb file using RJS?


I have a form that, when the user submits, and the user is not signed in, they receive a modal prompt to login. Once the user logs in, the modal disappears, but they have to click the submit button on the form again. It would be nice if, after successfully signing in, the modal disappeared and the form submits automatically.

So inside sessions/create.js.erb I added the following.

# create.js.erb
<% if signed_in? %>
    $('#ajax-modal').modal('hide').empty();
    $('#new_response).submit();
<% else %>
    $('#ajax-modal').html('<%= j render("sessions/form") %>').modal();
<% end %>

This works, but it's not scalable. Firs of all, I might have other forms--not just #new_response--that require a similar behaviour. So each time I add a new form I have to edit create.js.erb and add an if (form exists) submit();. There are also other times when the modal is used for signing in but no forms are involved at all.

Is there a way to attach a hook to tell sessions/create.js.erb to submit the form only when one exists, but without having any knowledge of the form id? Basically, have that passed in.

# responses/_form.html.slim
= form_for [@discussion, @response], remote: true do |f|
    = f.label :content, "Comments"
    = f.text_area :content, rows: 8
    = f.submit "Reply", class: 'btn btn-success reply', 'data-disable-with' => "Reply"

# Responses controller
class ResponsesController < ApplicationController
  before_filter :require_authentication, except: :index
  ...

  def require_authentication
    redirect_to signin_path unless signed_in?
  end
end

Solution

  • You can use some sort of way to track which form triggered the submit, e.g.

    # ResponsesController
    class ResponsesController < ApplicationController
      before_filter :require_authentication, except: :index
    
      def require_authentication
        session[:form_track_code] = params[:form_track_code] if [:put, :post].include?(request.method_symbol) && params[:form_track_code].present?
    
        redirect_to signin_path unless signed_in?
      end
    end
    
    # SessionsController
    class SessionsController < ApplicationController # or devise?
      def create
        @form_track_code = session.delete[:form_track_code]
        super # or whatever you implemented
      end
    end
    
    # create.js.erb
    <% if signed_in? %>
        $('#ajax-modal').modal('hide').empty();
        <% if @form_track_code.present? %>
          $('input[type=hidden][value="<%= @form_track_code %>"]').parents('form').submit();
        <% end %>
    <% else %>
        $('#ajax-modal').html('<%= j render("sessions/form") %>').modal();
    <% end %>
    
    # application.js
    $('form[data-remote=true]').each(function() { $(this).append('<input type="hidden" name="form_track_code" value="' + Math.random() + '" />'); });