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.
Related
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.
There is a similar question here and here but neither has the answer I'm looking for. I've also done a lot of searching for "rails format.js render" without being able to solve this.
In Rails 4, I have a validated form as follows:
<%= form_for(#message, :remote => true) do |form| %>
// don't want to call the js on submit here because
// I don't want it to execute if the form did not validate
I'm calling the js in the controller:
def create
#message = Message.new(params[:message])
if #message.valid?
NotificationsMailer.new_message(#message).deliver
respond_to do |format|
format.js { render "submit" }
end
else
render :new
end
end
I have "submit.js.erb" in the "messages" folder:
alert('js was called!');
When I submit the form, Terminal verifies the file DOES render:
Rendered messages/submit.js.erb (0.5ms)
...but on the screen, nothing happens. No alert, and no executed javascript. I've also tried creating "submit.html.erb" and wrapping my javscript in a script tag, and the same thing happens - the file loads, but the script does not execute.
Why? What do I need to do to tell Rails to execute the js?
Edit: After visiting Kelvo's resources and trying many things, the answer seemed to be adding this to the application.js...
$.ajaxSetup({
'beforeSend': function (xhr) {xhr.setRequestHeader('Content-Type', 'application/javascript');}
});
It also turned out that a manual line break and indentation (since it was not wrapping in my IDE) in my actual "submit.js.erb" was causing it to fail to execute, so there were really two problems.
This may be due to the fact that the returned content is not being evaluated. The browser does receive the file but does not know what to do with it, you have to include some JavaScript to handle the response as explained here :
You probably don't want to just sit there with a filled out <form>, though. You probably want to do something upon a successful submission. To do that, bind to the ajax:success event. On failure, use ajax:error. Check it out:
in your case you might try out
$(document).ready(function(){
$("#new_message").on("ajax:success", function (e, data, status, xhr){
eval(xhr.responseText);
});
});
in order to evaluate the js code.
you can read more on events fired during "data-remote" requests here
EDIT : forgot to mention, this script has to be included on the HTML file containing the form. Maybe just add it under your form.
This may be due to, returned content also including your default layout.
Try this:
format.js {render layout: 'no_layout', action: 'submit'}
Hope this helps...
Check this out. I've got a fairly simple form that's created with the following syntax:
<%= form_for([#issue, #issue_order], :remote => true) do |f| %>
The form, due to logic on the page, is actually called via javascript, like this:
$('#new_issue_order')[0].submit()
The controller handles the ajax request by doing a bit of logic then throwing out a little something like this:
respond_to do |format|
format.js
end
The AJAX that handles this response is in the following javascript:
$('#new_issue_order').on('ajax:success', issueOrder.processOrder)
..........
processOrder: function(e, data, status, xhr) {
$('.sign-up-errors').empty();
errors = xhr.getResponseHeader('X-Flash-Error').split(',');
for (i=0; i < errors.length; i++) {
$('.errors').append($('<p>' + errors[i] + '</p>'));
}
setTimeout(function() {
$('.errors').empty();
}, 3500);ยท
}
I figured that would allow it to respond to the remote request, but what I get instead is the following error:
ActionController::UnknownFormat
I tried creating a new.js.erb in my views (to correspond with the new page that it was on), but I'm still getting the same error. I haven't tried migrating my success handler AJAX to the new.js.erb code, because I'd prefer to keep my javascript handling in the javascript file in my assets for business reasons.
How can I get a seamless AJAX response? I've done it before, but respond_to has always confused me.
Setting the js response template as new.js.erb is incorrect.
The form itself is within new.html.erb template, guessed by convention. So, the form's action is supposed to point to #create.
In order to response correctly to this form's submission, you need to create a js template as create.js.erb, and respond to js in #create action.
Besides, in most cases you don't need to manually set Ajax response in assets js like
$('#new_issue_order').on('ajax:success', issueOrder.processOrder)...
Instead, you can just do it within create.js.erb. For example
$('#new_issue_order').css('background', 'green')
This script will be run after ajax:success event.
I am building a form in rails that will edit an existing question via ajax.
After the form is submitted and the question has been updated, the update method in the controller renders update.js.erb, which will hide the form again.
My problem is that the javascript code in update.js.erb is not executing at all.
I know that the file is rendering because it shows up in the server output, and when I put a
<% raise params %>
into it, it works.
However, even the simplest
alert('hello');
has no effect in the same file.
I've ruled out javascript and jquery configuration issues because the same code works perfectly in my edit.js.erb file. It's just not working in update.js.erb.
What am I missing?
Edit:
Firebug shows no errors. Here is the response in firebug's network panel:
alert('hello');
$('#question_body').replaceWith('<h4><p>jhsdfjhdsb k jdfs j fjfhds <strong>jfshaflksd;hf sdldfs l fdsalkhdfskhdfs</strong>;fd lfdksh hfdjaadfhsjladfhsjadfs ;df sjldfsj dfas hafdsj fdas ;ldfas ldfs df dl;hdf fdh ;fdj ;lfads</p></h4>');
def update
Edit 2:
This is the controller action:
def update
respond_to do |format|
if #question.update_attributes(params[:question])
format.html { redirect_to #question, :flash => { :success => 'Question was successfully updated.' } }
format.json { head :no_content }
format.js {}
else
format.html { render action: "edit" }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
In your $.ajax call make sure to set the dataType option to "script" otherwise the response could be interpreted in other ways and thus not executed as JS.
Do you work with haml, or html.erb? If the former, then this might be the solution:
respond_to do |format|
...
format.js {render layout: false}
end
I had the exact same problem, found this question early on, took another hour or so of Googling to find this question on StackOverflow that led me to it: jQuery + Ajax + Haml. js.erb files not firing
In your update.js.erb file you need to escape javascript wherever you execute ruby code.
$('.container').empty().append('<%=
escape_javascript(
render 'update'
)
%>')
This is what solved it for me ...
This issue isn't just because of Controller side. It is also can be in the View side which is you didn't clarify the data-type of your post request.
Make sure in your console that the request is treated as JS.
Reference: Similar issue
I ran into the same issue and found this page. I tried methods listed here but found no luck. While later the following method solve my issue.
My originally code was:
$('#html_id').html('<%=#ruby_variable%>');
And I updated it to:
$('#html_id').html('<%=raw #ruby_variable.to_json%>');
Now it works as expected.
Found out what it is! ๐ (solution for rails 4)
If you have in your ajax call parameters that are not in your permitted list, the record gets saved, you get no error messages about the 'not permitted' parameters, but the update.js.erb won't run - even though your terminal will feed back 'Rendered update.js.erb etc'
If the extra parameter is an attribute in your model, just permit it.
The simplest way to permit non model parameter is to add in your model:
attr_accessor :paramKeyTroublesome
Then you can also permit it in the controller.
in the $ajax call, data needs to be hashed up properly:
data: {model_name: {paramKey1: value, paramKeyTroublesome: value}}
One more problem to be aware of is an error in your update.js file. Nothing will execute if there are any syntax errors. You can check this by going to your browser inspector and enabling Log XMLHttpRequests Then reviewing the output js file.
I am trying to update a div in my rails application. Iam just learning ROR. So Its a learning stage for me.Please find the code.
In view page...
<%= javascript_tag do %>
jQuery(function($)
{
$("#tabs4").click(function()
{
$.ajax(
{
url:'/spaces/showcal',
type:'GET'
});
});
});
<% end %>
In spaces controller..
def showcal
respond_to do |format|
format.html
{
render (:update) { |page|
page.replace_html 'tab4', :partial => 'spaces/showcal'
}}
end
end
What am I doing wrong here.. Please help
I also have a partials page (_showcal)which has some text to display into that div.
When using ajax, a good way to debug this kind of thing is see what response the server returns. If it looks good, then you know your javascript code needs to change to get it working, if it looks wrong, then fix the server side code first.
Here's how i would do it:
def showcal
render :layout => false
end
#showcal.html.erb
<%= render :partial => "spaces/showcal" %>
Your js block:
jQuery(function($)
{
$("#tabs4").click(function()
{
$.ajax({
url:'/spaces/showcal',
type:'GET',
success: function(data)
{
$('#tab4').html(data);
}
});
});
});
I generally prefer using javascript as supposed to rails built in code when it comes to replacing and using content with ajax. I have to admit, because of this, I'm not sure if your update action was mostly correct or not. The page.replace_html should work if you're using the prototype helpers. The only thing is because you are doing an ajax request to achieve it and the resulting body would contain that code, and it would not execute on your current dom. So i think that was probably executing, but because it's on a separate page response, it didnt do anything.
Give my suggestions a try, and let me know how it goes. Sorry that my answer is a bit hazy.
You should request /spaces/showcal.js and react to format.js.
I never worked with $.ajax, you might need to set additional parameters there. With script.aculo.us, something like this works:
new Ajax.Request('/tasks/#{task.id}.js',
{asynchronous:true, evalScripts:true, method:'get'});