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.
Related
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'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
My plan was to update a partial via a klick-event where I fetch some data via ajax.
So i opened my assets/javascripts directory and put the code in the js file of the module I planed to call it on. I managed to fetch the data and to call some "html() or text()" on the div. But as soon as I tried to call
.html("<%= escape_javascript( render( :partial => 'job') ) %>")
my controller told me unknown method "render". So I red in many other Threats that the assets directory was not build for static content.
But now comes the question where to put it if not in assets?
I tried to put it in the view/model folder (with the same name as the aktion 'show'). But it wouldn't load. Yes I told the Controller in the show action to respond_to format.js.
So where should I put the js-File and how to call it? Or is there even a method to let it in the assets-directory and beeing able to call render?
Thanks for your answer! Sadly I do exactly that but I doesnt work. So here is my Code:
/app/views/events/show.js.erb.coffee:
$(document).ready ->
url = window.location
url = String(url).split('/')
event_id = url[$.inArray( "events" , url) + 1]
$('.position').click ->
position_id = $(this).attr("id")
$.ajax '/events/'+event_id+'/eventpositions/'+position_id+'/eventjobs'
dataType: 'json'
success: (result)->
$( '#'+position_id ).find('.jobs').html("<%= escape_javascript( render( :partial => 'job') ) %>")
alert result[1].job_id
/app/views/events/show.html.haml:
%p#notice{:xmlns => "http://www.w3.org/1999/html"}= notice
%p
%b Name:
= #event.name
\
%b Plz:
= #event.plz
%p
%b Personal:
- #eventpositions.each do |p|
.position{:id => "#{p.id}"}
%b
Position: #{Position.find(p.position_id).name} Anzahl: #{p.quantity} Aufträge: #{p.eventjobs.all.count}
.jobs
= link_to 'Neuer Auftrag', new_event_eventposition_eventjob_path(#event.id,p.id)
%br
%br
= link_to 'Neue Position', new_event_eventposition_path(#event.id)
= link_to 'Edit', edit_event_path(#event)
|
\#{link_to 'Back', events_path}
/app/views/events/_job.html.haml:
.jobs
- eventjobs.each do |j|
User: #{User.find(Job.find(j.job_id).user_id).email}
%br
/app/controllers/events_controller.rb:
def show
#agency = Agency.find(current_agent.agency_id)
#event = #agency.events.find(params[:id])
#eventpositions = #event.eventpositions.all
respond_to do |format|
format.html # show.html.erb
format.json { render json: #event }
format.js
end
end
So the Code does work without Javascript. All renders and is fine. But my main Problem now is that it wont even react to a click event if I place it in the app/views/events Folder. As soon as I place it in the assets directory I works like a charm, but wont render.
So what am I missing? Why does my js Code does not get loaded?
Thanks a lot for your help!
Generally for this kind of thing, I'll name it the same as a particular action, such as show.js.erb, and then use the format.js as you have in the controller. If you're using coffeescript, it will need to be named show.js.coffee.erb. If this does not work, can you post the code of your view where this onclick event is setup?
Edit for using the show javascript code
Because you're using the show action, should just be able to do this:
= link_to "Show", #event, :remote => true, :format => :js
Adjust the event variable there as you need to, but it should work
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!
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.