I've added :remote => true to the _form.html.erb and wondered now how I can get it so when the user saves what's on the page, it saves and then comes up with a notice.
In my documents_controller.rb, I have;
def create
#document = current_user.documents.build(params[:document])
if #document.save
redirect_to #document.edit, notice: 'Saved'
else
render action: "new"
end
end
def update
#document = current_user.documents.find_by_url_id(params[:id])
if #document.update_attributes(params[:document])
redirect_to #document, notice: 'Saved'
else
render action: "edit"
end
end
You'll need to write the appropriate JavaScript to make use of the following jQuery events:
ajax:beforeSend
ajax:complete
ajax:success
ajax:error
E.g.
$(document).ready(
$(".ajax_rails_link").bind("ajax:success", function(evt, data, status, xhr){
console.log(data);
// Display your notice logic goes here
})
});
More information can be found here: http://guides.rubyonrails.org/ajax_on_rails.html
Related
I have a form which submits number of info in Db.This form is on a modal popup. On click of submit tag, a new modal popup is displayed which has two buttons on click they show the data which the form has submitted.
Now the problem is till when the controller call is finished, these buttons do nothing on click.
So i want to add a spinner on the form popup on click of the submit button. and when the response comes true/ successful it shows the next popup.
my code looks like this:
form:
= form_tag("/system/upload_form", method: 'post', enctype: 'multipart/form-data', remote: true) do
...
...
=submit_tag("Submit",id: "submit_button", class: 'btn btn-default')
controller:
sys = #system.update!(system_params)
respond_to do |format|
format.js
format.json { render :json => sys }
js:
$("#submit_button").click(function() {
$('#modal_define_system').modal('hide'); // current popup
$('#next-page').modal('show'); // next popup
});
Now i want to know how and where to access the json object or sys value returned from the controller.
I tried:
Adding a class to the form and then
$('.form_class').bind('ajax:success', function() {
console.log(sys);
});
But could not succeed.Plese help and advise. Comment if i need to add some more code or explanation.
You are using form form_tag with remote true, which send the ajax request with js format not the json. If you render json response in js block instead of json in the controller like below, it should work.
respond_to do |format|
format.js { render :json => sys } #this will be rendered
format.json { render :json => sys } #this won't
end
Alternately you can render javascript file like this
$('#results_div').html("<%= #system.try(:title) %>")
in update.js.erb
Hope this helps.
extending maximus' code, you can use ajax to submit the form which can
be more easy for you as per your case. You can try
$("#theForm").ajaxSubmit({url: '/system/upload_form',
type: 'post'}).success(function(data){
$('#newModalContainer').html(data);
});
and in your controller, render html of your modal you want to show with your submitted values which can be passed in instance variables.
something like
def upload_form
#your logic
render :partial => 'new_modal_to_show'
end
this is a generic structure and you can change it to your relevant values. Hope it helps :-)
I have my onclick event working but when it comes to displaying the partial it:
only displays the text:
<%= escape_javascript(render(:partial => payment)) %>
I want it to fetch the parial and display it
here is my code:
$(".payment").append("<%= escape_javascript(render(:partial => payment)) %>");
tried with "" and '' around payment
full jquery code for this
$(document).ready ->
$('.plans').change ->
$(".payment").append("<%= escape_javascript(render(:partial => 'payment')) %>");
edit:
this worked for me if anyone looks at this in the future since i use devise:
devise_scope :user do
get 'registrations/toggle_partial' => "registrations#toggle_partial"
end
put the toggle_partial.js file in
views/devise/registrations
everything else that NickM put there is great....
also remember the '' around the partial name
Based on the 'full jquery' code you have above I'm guessing you have this in a coffeescript file, which does not have access to the render method.
You're going to have to set up a route that hits a controller action that renders the JS, like this:
routes.rb:
get 'controller_name/toggle_partial' => "controller_name#toggle_partial"
In that controller:
def toggle_partial
respond_to do |format|
format.js
end
And in views/controller_name add a file called toggle_partial.js with these contents:
$(".payment").append("<%= escape_javascript(render(:partial => payment)) %>");
Then in your coffeescript file do something like this:
$('.plans').change ->
$.ajax(
type: 'GET'
url: '/controller_name/toggle_partial'
success: ( data, status, xhr ) ->
)
Sorry if the indentation is off on the coffeescript example. The bottom line is that you don't have access to render in the coffeescript file so you have to make a work-around.
Hope this helps.
Hi want to implement ajax in my ruby on rails tutorials and the controller will return an object on handling the ajax request. I dont know to handle the response in my javascript file.
I want to update some div based on object returned in javascript file.
Here is what I have written in my showcomments.js.erb
$('.show_comment').bind('ajax:success', function() {
$(this).closest('tr')="Something here from the object returned");
});
My link where ajax call is called is via this line of code
<td><%= link_to 'Show Comment', :action => 'showcomment' , :id =>article, :remote => true ,:class=>'show_comment' %></td>
My controller action where this request is handled is like this
def showcomment
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
respond_to do |format|
format.js{ render :nothing => true }
end
end
How can this be done?
I just wanted to try and expand on the other answers a little bit.
In rails when you add :remote => true to a link it essentially takes care of the first part of a jquery ajax call. That's why you don't need bind.(ajax:success, function(){ #
do stuff here });
This is a typical jquery ajax call
$.ajax({
url: "test.html",
type: "POST"
}).done(function() {
$( this ).addClass( "done" );
});
Rails takes care of the first part, up to the .done callback. So anything in your javascript erb template is put in the callback like this
.done(function() {
#your showcomments.js.erb file is inserted here
});
To render the showcomments.js.erb template from the controller just do this
def showcomment
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
respond_to do |format|
format.js
end
end
You don't need anything after format.js because the default rails action at that point is to render a js template with the same name as the action, in this case it's showcomment.js.erb.
Now you know when that link is clicked it will go straight to rendering that showcomment template , and any javascript in there will be run instantly. Rails makes using ajax very simple. I hope that helps.
change showcomment to this:
def showcomment
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
respond_to { |format| format.js }
end
In showcomments.js.erb you can access both objects #article and #comment.
A sample use is as below:
$('#yourdiv').html('<%= #article.name %>');
You render nothing when responding to js format. So code in showcomments.js.erb isn't evaluated. Remove { render :nothing => true } in controller and do whatever you want in showcomments.js.erb. BTW you don't need ajax:success event. It is the end of request already.
showcomments.js.erb
$('.show_comment').closest('tr').html("<%= # you may render partial here or whatever %>");
I have a pretty standard Rails HAML new object form that does the usual stuff and ends with:
= f.submit "Add scenario"
This works perfectly, and the scenarios_controller.rb is also a straightforward:
def create
...create scenario...
redirect_to scenarios_path
end
However, I have also developed a wizard-type form that needs to do some JavaScript on pressing my button:
= f.submit "Add scenario", :onclick => "return validateForm()"
In my CoffeeScript, I collect up all the information and finish up with:
$.post(
url
data
(data, textStatus, jqXHR) ->
# How do I follow the redirect?
return false
My url and data are correct as the above controller works correctly and creates my object, but my page doesn't redirect to scenarios_path. I think I should be doing something with the post result, but searching around the web I cannot find out what, and examining the returned fields in Chrome's debugger doesn't suggest anything. The only suggestion I saw was to use data.redirect, but such a field doesn't exist, although jqXHR.responseText seems to contain the page I want to redirect to.
I'd treat the HTML call to Scenario#create and the JS call to Scenario#create differently, using a respond_to block.
In your scenarios_controller.rb file:
def create
# create your object
respond_to do |format|
format.html do
redirect_to scenarios_path
end
format.js
end
end
In views/layouts/scenarios/create.js.erb, then put something like:
window.location.replace("<%= scenarios_path %>");
When you call Scenario#create with JS, the create.js.erb file gets rendered and forces the redirect. When you call Scenario#create with HTML, the redirect_to call happens as usual.
I've got the following form:
<%= form_for [#commentable, Comment.new], :remote => true do |f| %>
<%= f.text_area :body %>
<%= f.submit "Add your comment" %>
<% end %>
Then the controller (heavily stripped down to the basic part):
def create
respond_with(#comment) do |format|
format.html { redirect_to params[:return_url] }
format.json { render :layout => !request.xhr? }
end
end
Then here is the javascript for handling the form AJAX:
$('#new_comment')
.bind('ajax:success', function(evt, data, status, xhr){
var $this = $(this);
// Append response HTML (i.e. the comment partial or helper)
$('#comments ol').append(xhr.responseText);
$('#comments ol li:last-child').effect("highlight", {}, 3000);
// Clear out the form so it can be used again
$this.find('input:text,textarea').val('');
// Clear out the errors from previous attempts
$this.find('.errors').empty();
})
.bind('ajax:error', function(evt, xhr, status, error){
// Display the errors (i.e. an error partial or helper)
$(this).find('.errors').html(xhr.responseText);
});
The form submits fine and the comment gets appended as it should, but Safari's Web Inspector shows a SyntaxError: Parse error on line 1 (which is just the doctype) of whatever page I'm on when the comment form is submitted, and I can't figure out why.
Not even sure where to start with this one.
I have gotten that error and it was because the remote ajax call was expecting JavaScript and I was returning html. The .ajax call was defaulting to dataType 'script' so when it got the ajax result, it tried to evaluate it and any < tags caused the error.
I got rid of the error by changing the view from .js.erb to .html.erb and adding 'data-type' => 'html' to the link that contained :remote => true.
In some cases, it may make sense to have the form itself be a JavaScript snippet - something like:
$('#container').replace("<%= escape_javascript(render(...)) %>");
Then you can omit the data-type from the link.
More information about data-type here.
Try putting your bind call on the same line as the new_comment reference:
$('#new_comment').bind('ajax:success', function(evt, data, status, xhr){
I think you're looking at the wrong line 1 - are you including your JavaScript files, it might mean line 1 of one of them. It might also mean line 1 of what's being sent back.
To be honest - try Chrome and switch on the debugging, Chrome is much better at saying which file gave it the problem and where.
You don't need to put all the JQuery in your file anyway - you can write a response in a view if you have the right gems installed - not sure if that would help.
Do you have a div on the page with class "errors"? I was having a very similar problem, and found this question while searching for a solution.
My issue was that we were trying to write back to a div that didn't exist (because of an unless .empty? on the page). When we solved that, the success callback worked.