Rails double render - javascript

I know this isn't valid code, but is there a way to do something like this in Rails?:
render "$('#dialog').replaceWith(#{render :action => 'new.html.erb'});"
What I'm trying to do basically is replace the contents of a JS dialog with what is/would be returned from calling render 'new.html.erb'.
Edit for #Devin M:
controller action:
def new
#act = Act.new(:user_id => current_user.id)
end
def create
#act = Act.new(params[:act])
if #act.valid?
#act.save
else
render :action => :new
end
end
new.js.erb:
$('#dialog').replaceWith("<%= escape_javascript(render(:action => 'new.html.erb')) %>");
Full error:
Showing app/views/acts/new.js.erb where line #1 raised: undefined method `formats' for nil:NilClass

You should split this code out into a seperate view since including it in the controller would go against the ideas of MVC. I would update the controller to respond to JS requests using some code like this in the action I wanted to modify:
respond_to do |format|
format.html { redirect_to #item }
format.js
end
And create a view like this with the extenstion .js.erb:
$('#dialog').replaceWith("<%= escape_javascript(render :partial => "new.html.erb", :locals => { :act => #act }) %>");
You can then trigger this JS with a remote link to the action or by adding your own UJS.

Related

Ajax success callback in ruby on rails

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 %>");

rails jquery ajax request not executing

I am implementing an up-voting system on an app I am building very similar to the one here on stackoverflow. When a user clicks upvote or downvote, an ajax request is sent to one of my controllers which them updates a couple of tables. Once that is done, I use the respond_to to routes to a js.erb file that executes jquery to update the user display. However, the jquery is not being executed. When I lick upvote/downvote, the controller code executes properly (I can see it in the rails console), but the user display is not updated. Upon refresh the user display is updated, however, not asynchronously. I know the jquery is not being executed b/c in the fire bug console I can see my jquery code - it just is not being applied. Here is my upvote controller code:
def upvote
#post = Post.find(params[:id])
#user_vote = current_user.votes.where(post_id: #post.id).first
if #user_vote.blank?
Vote.create(user_id: current_user.id, post_id: #post.id, vote: 1)
#post.upvotes += 1
elsif #user_vote.vote.to_i == 0
#user_vote.vote = 1
#post.upvotes += 1
elsif #user_vote.vote.to_i == 1
return redirect_to :back, :alert => 'You have already upvoted the post'
elsif #user_vote.vote.to_i == 2
#user_vote.vote = 1
#post.downvotes -= 1
#post.upvotes += 1
end
respond_to do |format|
if #post.save and #user_vote.save
format.js { }
else
format.html { redirect_to :back, :alert => 'There was an error in upvoting the post' }
end
end
end
This is my upvote.js.erb file:
$('#post-action-<%= #post.id %>').html("upvote");
// this normally renders a partial (below), but I am rendering "upvote" until I can fix this
// escape_javascript(<%= render :partial => 'post_voting', :locals => { post: #post, user_vote: #user_vote } %>)
Here is my html:
<div class="post_actions" id='post-action-<%= "#{post.id}" %>' >
<%= render :partial => 'post_voting', :locals => { post: post, user_vote: current_user.votes.where( post_id: post.id ).first } %>
</div>
Here is my firebug console output: http://i.imgur.com/H6zXJ.png
EDIT
I noticed I am getting an error in on my server:
Started GET "/assets/bootstrap.js?body=1" for 127.0.0.1 at 2012-08-09 06:33:42 -0700
Served asset /bootstrap.js - 304 Not Modified (0ms)
Your code seems OK and should execute. You might do an additional check to update a fixed id instead of the calculated id.
$('#updateme').html("upvote");
and add this id in your html somewhere. If this works, you are certain the ajax-call executes completely, and the problem is just the id you are referencing.
Have you checked your html-source that there is an id "post-action-2"?
After messing around with the jquery, I noticed some things. Firstly, I needed to minify my code (taking out all comments and unused spaces). I took this:
$('#post-action-<%= #post.id %>').html("upvote");
// this normally renders a partial (below), but I am rendering "upvote" until I can fix this
// escape_javascript(<%= render :partial => 'post_voting', :locals => { post: #post, user_vote: #user_vote } %>)
and changed it to this:
$('#post-action-<%= #post.id %>').html("upvote");
The code was then working and the user display was updating to show "upvote." Perfect. So then I replaced the above code with this:
$('#post-action-<%= "#{#post.id}" %>').html("<%= escape_javascript(render :partial => 'post_voting', :locals => { :post => #post, :user_vote => #user_vote }) %>");
and KAPOW! It works. So happy to have solved this! MINIFY YOUR JQUERY PEOPLE!

Rails 3 - respond_to as JS and flash message

After send a form I will process a data from form and wanna to render an action as JS. This work me.
But + this functionality I would like to add a flash message yet. I try to do it as follows:
respond_to do |format|
if #save.update_attributes(params[:data])
format.js {
flash[:notice] = 'The article was successfully updated.'
render :update do |page|; page << "$('#my_div').html('#{escape_javascript(render(:partial => 'article'))}');" end
}
format.html {}
else
format.html { render :action => "edit" }
format.xml { render :xml => #data.errors, :status => :unprocessable_entity }
end
Now the flash message is not displayed. Could anyone help me, why not? I tried the line with flash[:notice] move to out of format.js block, but the is still not displayed...
Could you help me, please, why?r
I guess you can use the point 2.2.10 of the documentation :
http://guides.rubyonrails.org/layouts_and_rendering.html#using-render
render :js => "$('#my_div').html('#{escape_javascript(render(:partial => 'article'))}');"

undefined method `formats' when rendering html.erb file

Im using Rails 3.0.3 and ruby 1.8.7
I want to render /materials/change_prize.html.erb in materials/change_prize.js.erb file.
change_prize.js.erb:
$("#content").html("<%= escape_javascript(render(:action => 'materials/change_prize.html.erb')) %>");
Materials Controller:
def change_prize
#material = Material.find(params[:id])
respond_to do |format|
format.js
format.html
end
end
routes.rb:
resources :materials do
member do
get 'change_prize'
post 'change_prize'
end
end
but when i load the js file i get this error:
undefined method `formats' for nil:NilClass
what am i doing wrong?
You need to use :partial not :action
<%= escape_javascript(render :partial => "materials/change_prize", :locals => { :xxxx => #xxxx }) %>
n.b. xxxx is if you need to pass your object to the partial
Partials have to begin with underscore. So rename your filename to "materials/change_prize.html.erb" to "materials/_change_prize.html.erb". Do note however that when calling it thru the render call you refer to the file WITHOUT the underscore.
$("#content").html("<%= escape_javascript(render(:action => 'materials/change_prize.html.erb')) %>");
Filename : app/views/materials/_change_prize.html.erb

AJAXy action accessible via "normal" request

Greetings,
I have an application which contains a calendar as alternative index view for Courses (Project has_many Courses). There I have two arrows for navigating to the next/previous month, it works via AJAX. Now, that's my action for updating the calendar:
def update_calendar
#project = Project.find params[:id]
#date = Date.parse(params[:date]).beginning_of_month
#courses = #project.courses.all(:conditions => {:date => (#date - 1.month)..(#date + 1.month)})
respond_to do |format|
# format.html { redirect_to :action => 'index' }
format.js { render :partial => 'calendar', :locals => {:calendar_date => #date, :courses => #courses} }
end
end
The important part is format.js { ... }. I thought it should just answer js/AJAX requests, but it doesn't. It renders the partial when I hit the URL http://localhost:3000/projects/1/update_calendar?date=2010-08-01 for example. I don't want that behaviour, I just want it to answer correctly when it's coming in via AJAX. Do I need to use request.xhr?? And what is format.js { ... } supposed to do than?
Best regards
Tobias
You need to tell it what you want to happen when someone goes to that action with an html request, ie you need to put your format.html block back in. If you don't have the braces it will do the default behaviour which is to show the update_calendar view. You probably want to redirect to a different action though.

Categories