I'm having trouble getting a Rails form_for form to work in a Bootstrap modal and update a table with AJAX. I've followed the guide at http://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html, to no avail. I've also tried following the advice in the links at the bottom of this question.
On the index view, I have a table of drivers and a button to add a new driver. The button brings up the modal with a form for a new driver. When the form is submitted, I want the modal to close and the new driver to appear in alphabetical order in the drivers table. What's happening now is that the modal comes up and shows the form, but clicking the submit button does nothing. The modal does not close and the new driver is not added to the database.
Here's a summary of app/views/drivers/index.html.erb:
<div>
Add Driver
<%= render 'new_driver' %>
</div>
<div>
<table id="drivers" class="table table-hover">
<thead>
<%= render 'list_header' %>
</thead>
<tbody>
<%= render #drivers.sort_by(&:last_name) %>
</tbody>
</table>
</div>
Here's the modal partial at app/views/drivers/_new_driver.html.erb:
<div id="driverAddModal", class="modal hide fade">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="driverAddModalLabel">Add Driver</h3>
</div>
<div class="modal-body">
<%= form_for #driver, remote: true do |f| %>
Last Name
<%= f.text_field :last_name %>
<!--more form fields-->
<%= f.submit "Add Driver", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
app/controllers/drivers_controller.rb:
class DriversController < ApplicationController
def new
#driver = Driver.new
end
def create
#driver = Driver.new(params[:driver])
respond_to do |format|
if #driver.save
format.html { redirect_to #driver, notice: 'Driver added.' }
format.js {}
format.json { render json: #driver, status: :created, location: #driver }
else
format.html { render action: "new" }
format.json { render json: #driver.errors, status: :unprocessable_entity }
end
end
end
def index
#driver = Driver.new
#drivers = Driver.all
respond_to do |format|
format.html
end
end
end
app/views/drivers/create.js.erb:
$("<%= escape_javascript(render #driver) %>").appendTo("#drivers");
app/assets/javascript/drivers.js.coffee:
$(document).ready ->
$("#new_driver").on("ajax:success", (e, data, status, xhr) ->
$("#new_driver").append xhr.responseText
).bind "ajax:error", (e, xhr, status, error) ->
$("#new_driver").append "<p>ERROR</p>"
Here are the other links I've checked out:
http://www.alfajango.com/blog/rails-3-remote-links-and-forms-data-type-with-jquery/
http://www.alfajango.com/blog/rails-3-remote-links-and-forms/
http://mrdanadams.com/2011/partials-ajax-form-submit-rails/#.UVDJuuC8K00
Rails App with Bootstrap Modal View containing form, submit and disappear modal view without reloading page
Displaying errors when a Twitter Bootstrap modal window contains a Rails form helper
"modal form" with bootstrap on rails works partially
Bootstrap modal not dismissing after form submit in Rails
Rails 3.1 and Twitter Bootstrap modal don't play nice?
Unfortunately I just don't know how to apply the advice on those pages to my app. I'm new to Rails and programming in general and this is my first foray into AJAX or JSON.
It seems like you are very new to Rails. In your case, I suggest you go and read the log files when you submit the form. And also log params[:driver] to see if all the fields are there, and watch for validation in your modal. puts driver.errors.inspect after driver.save to see if validation is the cause.
Sum up:
Check log if there is an submit request to your create controller.
output all params to see everything is submitted as expected.
output 'success' in success scope, and output driver.errors.inspect if save fail.
Then you are good to go to see all the bugs.
Oh I suggest you watch RailsCast, they got everything in there.
Related
I'm trying to build a kind of calculator with rails 5.2.
I need to update results fields while I'm writing my input fields. Everything is working perfect with AJAX if I press enter Key on my keyboard but it doesn't work if I try to automaticly submit the form as soon as a field is modified.
the view input.html.erb
<%= form_with url: achatproprietaire_output_path do |form| %>
<div class="form-group mb-3">
<%= form.label :credits_conso, "Montant des crédits conso", for:"example-helping" %>
<%= form.text_field :credits_conso, id: "example-helping", placeholder: "crédits conso", class: "form-control", id: "crédit_conso" %>
<span class="help-block"><small>en euros par mois</small></span>
</div>
js file calles un application.js
$(document).ready(function(){
$("#crédit_conso").keypress(function(){
//this.form.trigger('submit.rails');
Rails.fire(form, 'submit');
});
});
js.erb file correctly called with enter key
$('#output_col').replaceWith("<%= j render 'output', capacité_emprunt_maximal: #capacité_emprunt_maximal,
montant_mensuel_maximal: #montant_mensuel_maximal,
taux_interet: #taux_interet,
taux_assurance: #taux_assurance %>");
And I have no render or redirect_to in my controller.
I've also tried to put onchange: "Rails.fire(this.form, 'submit')" in the form fields but it submit the form without AJAX.
In some...controller.rb i have string
redirect_to posts_path, notice: 'Login or register'
In some...views.html.erb
<% if notice.present? %>
<div class="alert alert-info fade in">
×
<strong><%= notice %></strong>
</div>
<% end %>
In application.js i add
$(".alert-info" ).fadeOut(3000);
$(".alert" ).fadeOut(3000);
$(".alert-success" ).fadeOut(3000);
$(".alert-danger" ).fadeOut(3000);
but alert , do not want to close itself
what am I doing wrong ?
I think you are using jquery. You have to call $('.alert').delay(5000).fadeOut(); with in jquery $(document).ready method that ensure script executed after DOM loading.
First be sure that you add your application.js to your layout page.
Add following code
$(document).ready( function() {
$('.alert').delay(5000).fadeOut();
});
demo
I have a Rails ajax form to submit.When user will give the correct data it will search the database and do the operation accordingly.If user is giving the Wrong data it should display user to alert message.But it is not happening like that.
I am explaining my codes below.
home.html.erb
<% if current_admin %>
<p class="flash-message"><%=flash[:notice]%></p>
<div class="col-md-6" style="float:none; margin:auto;">
<%= form_for :sdf ,:url => {:action => "scan_report" },remote: true do |f| %>
<% if params[:receipt_no] %>
<div class="input-group bmargindiv1 col-md-12"> <span class="input-group-addon text-left">Receipt No. Scan :</span>
<%= f.text_field :Receipt_No,:class => "form-control", :value => params[:receipt_no] %><%= f.submit "Scan Report" %>
</div>
<% else %>
<div class="input-group bmargindiv1 col-md-12"> <span class="input-group-addon text-left">Receipt No. Scan :</span>
<%= f.text_field :Receipt_No,:class => "form-control",placeholder:"Receipt No. scan" %><%= f.submit "Scan Report" %>
</div>
<% end %>
<% end %>
<% end %>
controller/homes_contorller.rb
class HomesController < ApplicationController
def home
#sdf=TSdf.new
respond_to do |format|
format.html
format.js
end
end
def scan_report
if #sdf=TSdf.find_by_Receipt_No(params[:sdf][:Receipt_No])
if #sdf && #sdf.HCSY_Status=='YES'
#hcsy=THcsy.find_by_Sdp_Id(#sdf.Sdp_Id)
#hcsy_deatils=THcsyDetails.find_by_HCSY_ID(#hcsy.id)
#woods=THcsyFundTypeMaster.find_by_Fund_Type_Code(1)
#burn=THcsyFundTypeMaster.find_by_Fund_Type_Code(2)
#good=THcsyFundTypeMaster.find_by_Fund_Type_Code(3)
#swd=THcsyFundTypeMaster.find_by_Fund_Type_Code(5)
#photo=THcsyFundTypeMaster.find_by_Fund_Type_Code(6)
end
else
flash[:notice]="Not Found"
end
end
end
In this form its only taking the correct input but if user is trying to give the wrong input the else part is not executing.Please help me to resolve this error and let me to know how can i make this ajax call in below format.
$('form').submit(function() {
var valuesToSubmit = $(this).serialize();
$.ajax({
type: "POST",
url: $(this).attr('action'), //sumbits it to the given url of the form
data: valuesToSubmit,
dataType: "JSON" // you want a difference between normal and ajax-calls, and json is standard
}).success(function(json){
console.log("success", json);
});
return false; // prevents normal behaviour
});
Please help me.I am using Rails version 3.2.19.
Here you send AJAX POST request to scan_report, and if it is successful it should render template scan_report.js.erb, and rendered template will appear in json variable in success callback.
But if params are not valid, the same template is rendered, but all instance variables are missing. And probably empty json is returned or an error appears in log.
Anyway, if you'd like to change flash in remote form, you should put custom code in fail callback. Something like
$("#flash").html('<%= j render flash[:notice] %>');
I have 2 kinds of users - nurses and patients, and want to setup login such that there are two buttons on the welcome/landing page which open up a bootstrap modal with the login form for each type of user. I'd like the login form to send an AJAX request so that if there are errors, they are displayed in the modal itself.
I'm using Devise for authentication, and have setup 2 models for nurses and patients. Initially, I setup the modal to load the url for the new_nurse_session_path on clicking the button, modified the default devise login form to send AJAX requests, used a custom SessionsController to handle new sessions and send JSON replies back, and then have JS code which catches the reply. This worked (though with some issues as below) was pretty slow since it was loading the entire page from nurses/sessions/new.html.erb along with the header, navbar, etc.
Questions
While the JS code was catching the AJAX request when the entire sign in page was opened in the modal (as per code below), if I opened the page directly, the AJAX request wasn't processed even though the server was sending the correct JSON back - is there something I'm doing wrong here that might be causing this problem?
To avoid the entire new session page from being loaded in the modal, I followed the instructions here https://github.com/plataformatec/devise/wiki/How-To:-Display-a-custom-sign_in-form-anywhere-in-your-app to put the form in the modal. The issue I'm facing here is how to create the helper so that it defines the resource and Devise mappings according to whether it's a nurse or patient trying to login. If I create separate custom forms and modals for each one, I face the same issue with handling AJAX requests as in Q1. Would really appreciate help on what I might be doing wrong here.
If I'm going down a rabbit hole here, would really appreciate suggestions on implementing the above functionality in a better way! Thanks!
Code used
Login form, nurses/sessions/new.html.erb:
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name),
:html => {:id => "sign_in_nurse"}, :format => :json,
:remote => true) do |f| %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<% if devise_mapping.rememberable? -%>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<div><%= f.submit "Sign in" %></div>
<% end %>
<%= render "nurses/shared/links" %>
Coffeescript to handle AJAX reply, nurses.js.coffee:
$("form#sign_in_nurse").bind "ajax:success", (e, data, status, xhr) ->
if data.success
window.location.replace(data.redirect)
else
alert('failure!')
SessionsController:
class SessionsController < Devise::SessionsController
def create
resource = warden.authenticate!(:scope => resource_name, :recall => "sessions#failure")
return sign_in_and_redirect(resource_name, resource)
end
def sign_in_and_redirect(resource_or_scope, resource=nil)
scope = Devise::Mapping.find_scope!(resource_or_scope)
resource ||= resource_or_scope
sign_in(scope, resource) unless warden.user(scope) == resource
return render :json => {:success => true, :redirect => stored_location_for(scope) || after_sign_in_path_for(resource)}
end
def failure
return render :json => {:success => false, :errors => ["Login failed."]}
end
end
Code to generate modal:
<li><%= link_to image_tag('i_am_nurse.png', :size => "130x130"),
new_nurse_session_path , :data => { :target => "#ajax-modal", :toggle => "modal"} %></li>
Bootstrap modal div:
<div id="ajax-modal" class="modal hide fade" tabindex="-1">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="modal-body-content"></div>
<div class="ajax-loader"></div>
</div>
<div class='modal-footer'>
<button type="button" data-dismiss="modal" class="btn">Close</button>
</div>
</div>
I have a partial which returns results from the Amazon-ecs API (searches for books). It takes about 2.5 seconds to return values, so I want to add a spinner (and ideally hide the search button) but I've had a tough time getting it to work.
I already have javascript refreshing the partial with the results. I'd just like the button to give me a spinner (and hide the search button) until the partial finishes reloading.
Here is my main view (index.html.erb) which renders a partial of search results, each of which is added temporarily as an object in AmazonItems:
<%= form_tag amazon_items_path, :method => :get, :remote => true do %>
<p>
<%= text_field_tag :query, params[:query] %>
<span id="spinner" style="display:none">
<%= image_tag 'ajax-loader.gif' %>
</span>
<span id="search_button">
<%= submit_tag "Search" %>
</span>
</p>
<% end %>
<h1>Searching Amazon</h1>
<div id="amazon_returned">
<%= render 'amazon_returned' %>
</div>
My only JS code is in the update.js.erb file, which looks like:
$("#amazon_returned").html("<%=j render 'amazon_returned' %>");
I'm sure this is easy, but I can't get it work. Thanks!
EDIT: my partial "_amazon_returned.html.erb" looks like
<table>
<% for amazon_item in #amazon_items %>
<td> amazon_item.title </td>
...ETC...
<% end %>
</table>
You can hook into the before event to do this:
$(function() {
$("form").on("ajax:before", function() {
$("#spinner, #search_button").toggle();
});
});
Then, in your update.js.erb, add this again to toggle them back:
$("#spinner, #search_button").toggle();
Went with Dylan's answer, added the toggle to the update.js.erb and inserted the following into the view:
<script>
$(function() {
$("#search_button").click(function() {
$("#spinner, #search_button").toggle();
});
});
</script>
Very cool! Thanks again for the help.