How do I handle response from an Ajax Request in Rails 3? - ruby-on-rails

I have a CRUD application set up in Ruby on Rails 3 - its working as is. I need to add some ajax here. My first requirement is to retrieve a customised form when clicking on a New Form link. This is the link I have at this point:
<%= link_to 'New Book', new_book_path(:subject_id=>#subject.id), :remote=>true %>
For my controller I've made the following adjustment to the new book action:
def new
#book = Book.new
if params[:subject_id].to_i >0 then
#book.subject_id = params[:subject_id]
end
if request.xhr?
respond_to do |format|
format.html # new.html.erb
format.json { render json: #book }
render :layout => false, :file=>'app/views/books/_form'
return false
end
else
respond_to do |format|
format.html # new.html.erb
format.json { render json: #book }
end
end
end
I checked in firebug and clicking on the link generated returns the form html however I have no idea how to handle the response? Please do help.

Instead of responding with HTML respond with .js
Inside your .js.erb file could be something like this
$("#idname").append(<%= render "form" %>)
That way it renders and returns the form HTML but also gives the js code to append the HTML.

You can certainly rely on Rails generated JavaScript, but I always like to have "more control" over my JavaScript code. In e.g. jQuery you could have something like this (untested), if you want to insert the partial (html) rendered by your controller into the site:
$("#new-book-button").click( function () {
$.get('books/new', function(data) {
$('#some-form-container').html(data);
});
}

Related

How do I change the render file path for AJAX call

I'm running Rails 2.3.8 and I have a respond_to in my Projects controller create action.
def create
respond_to do |format|
format.html { redirect_to('/') }
format.json :status => 200
end
end
I have an AJAX call to this action. The Rails application then renders
projectdocs/create.erb
My question is, how can I change this file path within my action from create.erb to create.erb.js.
I think your controller-name would be "projectdocs" an not "Project" if he renders "projectdocs/create.erb", but that's not the point.
You can explicit render a js-file using
format.js { render :action => 'create' }
if this Format is requested.
It depends on called format. If client wants js, add format.js and rails will try to render first of all create.js.erb

Rails AJAX - don't redirect or render

Using rails and .js.erb to make an AJAX request (and append values to a div), how do you prevent rendering a new layout? In other words, stay on the same page without going anywhere and just append the fresh data from the server in a div. No reloading the same page, no redirecting.
At the moment my controller looks like this
def update_shipping
#order = Order.find(params[:id])
#order.shipping_option_id = params[:shipping_options]
#order.save!
respond_to do |format|
format.js
format.html
end
end
and my form like zisss:
<%= form_tag update_shipping_order_path(#order), method: :put, remote: true do %>
<%= select_tag 'shipping_options', #options_for_select, onchange: 'this.form.submit()' %>
<% end %>
and my routes look like a so:
resources :orders do
member do
put :update_shipping
end
end
But I get a 'Template is Missing' error
Please help!!
You need to add a update_shipping.js.erb file under app/views/your_controller/ directory. Note the name of the javascript file should be same as the action. Since you have a remote:true in your form so rails will try to render a javascript template in your case update_shipping.js.erb.
Now in your update_shipping.js.erb file write some basic javascript to update the page elements like
#update_shipping.js.erb
$('.some-div').html(<%=j #model.some_value' %>)
Try this:-
respond_to do |format|
format.js { render :nothing => true }
format.html
end
If you don't want to render a layout, you can use !request.xhr? like so:
respond_to do |format|
format.html { layout: !request.xhr? }
format.js
end
If you're looking to get your ajax-powered JS to fire, you just need to call your .js.erb file the same as your view:
#app/views/controller/update_shipping.js.erb
alert("This JS is returned & fired after the Ajax request");
You'll be best doing this in your routes.rb too:
resources :orders do
put :update_shipping
end
A little late, I came across this searching for the same issue. It must of slipped out of my mind at some point while working with action cable, but what is needed is a http response code of no_content. Http response codes tell the browser how to act when a request is returned. Here is a link to a list of them, and their symbols in rails. More on 204 no content
Here is how it would look:
def update_shipping
#order = Order.find(params[:id])
#order.shipping_option_id = params[:shipping_options]
#order.save!
head :no_content #or head 204
end
edit: what solved the solution for me was a link provided by William Denniss in this stack overflow question

jquery ajax render partial with rails view

I have my jquery ajax success as
success: function(data) {
$('#someId').html(data);
}
I have a partial file in the name of _information.html.erb
How do i render my ajax success response to rails partial view(information).
Most of the resources showing something like this
$('#holderDiv').empty().append('<ul> <%= j render #comments %> </li>')
But i didn't feel comfortable with it. Any other way to solve it.
UPDATE
Here's some more info in response to your comments.
First please read this Rails Guide on Javascript for more info.
update.js.erb is your view. Instead of having an update.html.erb file for your view, the respond_to block with format.js in your controller will send update.js.erb (formatted as javascript code) back to your jquery function.
update.js.erb could contain pure javascript. However it is processed by the server before being converted to javascript, so you can embed any ruby code you want. That ruby code gets converted into javascript.
If you use chrome developer tools, you can look in the "network" tab after your jquery call runs. You'll see a new entry appear for the AJAX call you just made. If you click on the entry, you'll see the javascript that was returned.
I've updated the update.js.erb file below slightly to show how you can put regular javascript code in the .js.erb file. The first line is javascript. The second line is ruby code which the server converts into javascript. So by the time that it gets to your browser, the entire update.js.erb file has been converted into javascript.
Hope that helps...
Original Answer Below:
Option 1:
Assuming that your jQuery success function is tied to the successful completion of a controller action (I'll use the edit action for my example), you would create a view called update.js.erb which will be called after a successful edit.
Controller:
if #user.update_attributes(params[:user])
respond_to do |format|
format.html { redirect_to #user, notice: "Successfully updated user." }
format.js
end
else
# ...
end
Because this is being called from javascript and you have format.js in the respond_to block, update.js.erb will automatically be called.
update.js.erb:
console.log('see... this is a regular javascript call.');
<%= render partial: 'information', format: 'js' %>
Option 2
The snippet you included:
$('#holderDiv').empty().append('<ul> <%= j render #comments %> </li>')
will only work in a js.erb file, where embedded ruby code is first processed then converted into javascript code. That would work in a situation such as:
Controller:
def create
user = User.new(params[:user])
respond_to do |format|
if #user.save
#comments = 'some comments to display!'
format.js
else
# ...
end
end
end
create.js.erb:
$('#holderDiv').empty().append('<%= j render #comments %>')

Rails: rendering the js.erb template using the controller

I have a rails app trying to incorporate some AJAX where clicking new opens a modal window and a form. I want to be able to display the validation errors if it fails so in my create action, i thought about re-rendering the new.js.erb file. Is this the right approach?
def create
#place = Place.new(params[:place])
if #place.save
redirect_to places_path, :notice => "Successfully created place"
else
render "new.js.erb"
end
end
The result I get is escaped js text in my browser like:
$("#new_grouping").html("<div class=\"modal-header\">\n <a class=\"close\" data- dismiss=\"modal\">×<\/a>\n <h3>Create a new menu section<\/h3>\n<\/div>\n<form accept-charset=\"UTF-8\" action=\"/places/1-mama-s-pizza/groupings\" class=\"simple_form new_grouping\" id=\"new_grouping\" method=\"post\" novalidate=\"novalidate\">
I've tried putting various options into the render block but no luck. Any tips?
The best practice would be to support both, AJAX and Non-AJAX calls, in case the user has javascript turned off for any reason.
def create
#place = Place.new(params[:place])
respond_to do |format|
if #place.save
format.html { redirect_to places_path, :notice => "Successfully created place" }
format.js # renders create.js.erb, which could be used to redirect via javascript
else
format.html { render :action => 'new' }
format.js { render :action => 'new' }
end
end
end
The render :action => 'new' actually renders the template of the controller action new which results to new.html.erb respectively to new.js.erb depending if it's a non-AJAX or an AJAX call.
In new.js.erb goes your ERB/javascript code:
$("#new_grouping").html("<%= escape_javascript(...) %>">
As i know, rendering partial in controller is a bad idea, because then response can be without content-type and some browsers can't understand this. if it is some file attached to action you should write
render :action => "create"
or if you need just render a singe partial then in your action file write
<%= render :partial => "path/to/partial" %>
as i said, then you won't have problems with content-type in response

How to return HTML directly from a Rails controller?

One of my model objects has a 'text' column that contains the full HTML of a web page.
I'd like to write a controller action that simply returns this HTML directly from the controller rather than passing it through the .erb templates like the rest of the actions on the controller.
My first thought was to pull this action into a new controller and make a custom .erb template with an empty layout, and just <%= modelObject.htmlContent %> in the template - but I wondered if there were a better way to do this in Rails.
In your controller respond_to block, you can use:
render :text => #model_object.html_content
or:
render :inline => "<%= #model_object.html_content %>"
So, something like:
def show
#model_object = ModelObject.find(params[:id])
respond_to do |format|
format.html { render :text => #model_object.html_content }
end
end
In latest Rails (4.1.x), at least, this is much simpler than the accepted answer:
def show
render html: '<div>html goes here</div>'.html_safe
end
Its works for me
def show
#model_object = ModelObject.find(params[:id])
respond_to do |format|
format.html { render :inline => "<%== #model_object['html'] %>" }
end
end

Resources