Remote Form Renders as HTML instead of JS - ajax

I have a simple form:
<%= form_for [current_user, #bookcase], :id => "shelf_update_form", :remote => true, :html => { :multipart => true} do |f| %>
<input id="bookcase_image" class="file" type="file" name="bookcase[image]" size="13">
<% end %>
That automatically uploads when a file has been selected:
$("#shelf_update_form").change(function() {
$("#shelf_update_form").submit();
});
I want the update action to render js view, but by default it renders html instead. I try forcing it to render js like so:
respond_to do |format|
format.js
end
But then I get this error:
NetworkError: 406 Not Acceptable
Even then, my log reports:
Processing by BookcasesController#update as HTML
How can I get it to process as JS instead?
UPDATE:
The view:
triggerAjaxHistory("<%= #href %>", false);
I get the same results with a more generic view, too:
alert("I work now!")

In the controller, do
respond_to do |format|
format.js if request.xhr?
end
Is your view named as .js.erb?
Can you check using firebug in your browser what exactly you are getting as the response? Turn on net logging and look at the response.
Also do you have the following in your layout?
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
Can you put in logger.info whatever_message commands to make sure you the controller action executes and you go into the correct view?
What happens if you specify the js format specifically in the controller as
class UserController < ApplicationController
respond_to :js, :only => :update, :layout => 'false`
What happens if you specify the format in form_for as :format => :js
Is your form nested within another form?

Related

Rails 3 -rendering partials and error "undefined local variable or method"

I have a photos in gallery (PhotosController) and I wanna add to every photo a comments. Into the statement of photos I added a partial for rendering comments + form for adding new comment.
My problem is, that when I send the form with a new comment, so I'll get the rendering error:
**NameError (undefined local variable or method `photo' for #<CommentsController:0x00000100ce0ad0>)**:
This is how looks my code:
views/photos/index.html.erb
<%= render #photos %>
views/photos/_photo.html.erb
<div><%=image_tag photo.photo.url(:thumb)%></div>
<div class="comments_to_photo">
<%= render :partial => 'photos/photo_comments', :locals => { :photo => photo }%>
</div>
photos/photo_comments
<%photo.comments.each do |cmnt|%>
<div><%=cmnt.comment%></div>
<%end%>
<%=form_tag comment_path, :remote => true do %>
<div><%=text_area_tag 'comment[comment]'%></div>
<%=submit_tag%>
<%end%>
controllers/CommentsController
def create
#comment = Comment.new(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to #comment, notice: 'Comment was successfully created.' }
format.js {
render :partial => '/photos/photo_comments', :locals => { :photo => photo } do |page|; page << "$(this).html('abcde');" end
}
else
format.html { render action: "new" }
format.js
end
end
end
I would like to refresh the form and comments statement in the photo, where was added a comment. Could anyone help me, please, how to avoid the error above?
Thank you in advance
EDIT: I added for refresh comments through AJAX the file _photo_comments.js.erb:
$('#photo_comment').html("<%= escape_javascript(render('photos/photo_comments')) %>");
And I get the error
ActionView::Template::Error (stack level too deep):
activesupport (3.2.1) lib/active_support/notifications/instrumenter.rb:23
with tens of this line:
Rendered photos/_photo_comments.js.erb (562.2ms)
and the last one
Completed 500 Internal Server Error in 580ms
What's wrong with rendering? I can't render partial html file from partial JS file?
In your controller you have:
:locals => { :photo => photo }
but the variable photo doesn't exist there. It should be:
:locals => { :photo => #comment.photo }
image_tag photo.photo.url(:thumb) <- Is it what you want to have photo.photo ?

Multiple pagination with kaminari via Ajax

I want to apply multiple pagination with Kaminari via Ajax now here is my code for controller
def user_note
#user = current_user
#notes = Bookmark.where('user_id = ? && note is not NULL',current_user.id).order('created_at DESC').page(params[:page_1]).per(4)
#bookmarks = Bookmark.where('user_id = ? && note is NULL',current_user.id).order('created_at DESC').page(params[:page_2]).per(4)
respond_to do |format|
format.html
format.xml{ render :xml => #user}
end end
now for views i have two partials to render this arrays
<div id="bookmarks">
<%= render :partial =>"users/bookmark",:locals => { :bookmark => #bookmarks} %>
</div>
<%= paginate #bookmarks,:remote => true, :param_name => 'page' %>
inner partial is
<% bookmark.each do |bookmar| %>
<%= render :partial => 'show_bookmark.html.erb' , :locals => { :bookma => bookmar} %>
<%end%>
script for pagination update is being handled in a separate file
$('#bookmarks').html('<%= escape_javascript render(:partial =>"users/bookmark",:locals => { :bookmark => #bookmarks}) %>');
$('#paginator').html('<%= escape_javascript(paginate(#bookmarks, :remote => true).to_s) %>');
But by doing every thing it is not updating to state of page neither the contain in the page.
you are missing to pass params at this line
$('#paginator').html('<%= escape_javascript(paginate(#bookmarks, :remote => true).to_s) %>');
i think it should be like this
$('#paginator').html('<%= escape_javascript(paginate(#bookmarks, :remote => true, :param_name => 'page_2').to_s) %>');
and you are also passing wrong param at this line
<%= paginate #bookmarks,:remote => true, :param_name => 'page' %>
it should be like this
<%= paginate #bookmarks,:remote => true, :param_name => 'page_2' %>
and please also check that whether you are sending the response correctly to the JS file or not.
I found this question searching for paginating multiple models on the same page. It's not clear to me how the pagination for the #notes collection is intended to work, but as presented, the solutions will only paginate the #bookmarks collection via AJAX.
There will be issues if you want to maintain pagination for both collections via html OR if you change the js file to render both collections.
I implemented a solution to my similar problem like this:
An html view that renders a template with two partials: one for #notes (including its pagination helper) and another that renders #bookmarks with its pagination helper
Pagination links marked with remote: true
One js view that re-renders the two partials, something like
$('#notes_container').html('<%= j(render partial: 'paginated_notes_list') %>');
$('#bookmarks_container').html('<%= j(render partial: 'paginated_bookmarks_list'); %>');
This is the key: Pagination links that take the current page of the other model as a parameter. This way you do not "lose" which page you are on in the other model.
<%= paginate #notes, param_name: 'page_1', params: {page_2: params[:page_2]} %>
<%= paginate #bookmarks, param_name: 'page_2', params: {page_1: params[:page_1]} %>
Again, I'm not really clear on how the asker's system is supposed to function, but this solution will allow user to page through both models without losing their "place" in the other model via AJAX or html.

RoutingError when using jQuery UI tabs with ajax

I'm getting ActionController::RoutingError in Profiles#show when I click a link to render a layout as part of my implementation of jQuery UI tabs. Here's my link_to:
<%= link_to "Messages", :controller => 'profiles', :action => 'profile_messages', :remote => true %>
My ProfilesController:
def profile_messages
#messages = User.find(#profile.user_id).messages
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #messages }
end
end
My profile_messages erb layout:
<div id="tabs-2">
<% for message in #user.messages %>
<div class="message-1">
</div>
<% end %>
</div><!-- end messages -->
Routes.rb:
resources :messages do
get "messages/profile" => :profile_messages
resources :responses
end
What I want to happen is: when you click the link created by my link_to, the layout in profile_messages.html.erb shows and loads the messages in that specific layout. What's going on here?
UPDATE: Adding the new line in Routes.rb gives me a new route:
message_messages_profile GET /messages/:message_id/messages/profile(.:format) {:action=>"profile_messages", :controller=>"messages"}
So I tried this in my Profiles show.html.erb I put:
<li><%= link_to "Messages", message_messages_profile_path, :remote => true %></li>
This gives me a RoutingError in Profiles#show -- No route matches {:action=>"profile_messages", :controller=>"messages"}. Even when I add the following into my MessagesController:
def profile_messages
#message = #user.messages.find(params[:user_id])
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #messages }
end
end
get "messages/profile" => "messages#profile_messages", :as => profile_messages
resource :messages do
resource :responses
end
You don't have a route for that controller action. Rails doesn't map ":controller/:action/:id" by default any more. You can also just enable that route if you want. You could be able to reference this via profile_messages_path.
It's assuming 'show' is actually an id for messages here I think. The default routes for a resource are listed here: http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions. Make sure you list your routes first!
resource :messages do
collection do
get :profile_messages
end
end
in your view
<li><%= link_to "Messages", "/messages/profile_messages", :remote => true %></li>
Thanks to the combined efforts of folks here on SO I was able to get this to work. Check out these questions for more code:
Exclude application layout in Rails 3 div
Rails 3 jQuery UI Tabs issue loading with Ajax

Problem using link_to with remote option in rails 3

I'm working on rails 3 with link_to remote option.
This is my code structure.
View/punch/report.html.erb :
<%= link_to 'Punch report', punchreport_punch_index_path, :remote => true%>
<div id="punchform"> </div>
View/punch/punchreport.js.erb :
$("#punchform").html("<%= escape_javascript(render(:partial => "reportform"))%>");
and created a form inside
View/punch/_reportform.html.erb
and controller :
controller/punch_controller.rb
def report
end
def punchreport
respond_to do |format|
format.html { render report_punch_index_path }
format.js
end
end
note : punchreport_punch_index_path : /punch/punchreport
report_punch_index_path : /punch/report
I don get the ajax request working. instead of that, it redirects the page.
Any help
Thanks in advance
Sounds like your :remote => true is not being handled by an unobstrusive javascript event handler...
Do you have something called jquery-rails in your project? it should set a handler on "data-remote" attribute. Can you find it and post back what you have there?

link_to remote=>true not updating with ajax

Using rails3 and prototype (rails.js)
I have a simple list of products with edit and delete links as images.
When deleting a product, the list is not updated. Refreshing the page shows that the product has indeed been deleted.
/app/views/products/list.rhtml
<div id="product_list">
<%= render :partial => 'list' %>
</div>
/app/views/products/_list.rhtml
<%= link_to image_tag("delete.png"), { :controller => 'products', :action => 'destroy', :id => product }, :method => :delete, :confirm => "Are you sure?", :remote => true %>
/app/controllers/products.rb
def destroy
Product.find(params[:id]).destroy
#products = Product.all
end
/app/views/products/destroy.rjs (not sure what to do with that...)
$(document).ready(function() {
$("#product_list").html("<%= escape_javascript( render(:partial => "list") ) %>");
});
So the remote link seems to work fine.
I'm not sure how to use the ajax callback to update #product_list
I tried to put the following in the head of the page:
$(document).ready(function(){
$('#product_list').bind("ajax:success", function(evt, data, status, xhr){
alert('hello');
})
});
But it's not executed (that's probably not a valid code for prototype) and I wouldn't know anyway what code to put inside so that my list gets updated after destroying a product
Any help (other than "use jQuery") is greatly appreciated!
EDIT: Here is the server log for the delete action (after I moved the javascript above to destroy.js.erb)
Started POST "/products/destroy/3" for 127.0.0.1 at .....
Processing by ProductsController#destroy as JS
Parameters: {"_"=>"", "id"=>"3"}
[1m[36mProduct Load (0.0ms)[0m [1mSELECT `products`.* FROM `products` WHERE (`products`.`id` = 3) LIMIT 1[0m
[1m[35mSQL (0.0ms)[0m BEGIN
[1m[36mSQL (0.0ms)[0m [1mDELETE FROM `products` WHERE (`products`.`id` = 3)[0m
[1m[35mSQL (78.1ms)[0m COMMIT
[1m[36mProduct Load (0.0ms)[0m [1mSELECT `products`.* FROM `products`[0m
Rendered products/destroy.js.erb within layouts/standard (31.2ms)
Completed 200 OK in 312ms (Views: 62.5ms | ActiveRecord: 78.1ms)
Processing by ProductsController#destroy as JS so the remote link works
[36mProduct Load (0.0ms)[0m [1mSELECT products. FROM products* The #products = Product.all is executed
Rendered products/destroy.js.erb within layouts/standard the javascript fie is rendered
So now I guess it's a problem with the javascript code:
$(document).ready(function() {
$("#product_list").html("<%= escape_javascript( render(:partial => "list") ) %>");
});
Is that kind of code supported by prototype? I don't use jQuery...
Found the answer on my own:
/app/controllers/products.rb
def destroy
Product.find(params[:id]).destroy
#products = Product.all
respond_to do |format|
format.js { render :layout=>false }
end
end
/app/views/products/destroy.js.erb
$("product_list").update("<%= escape_javascript(render(:partial => "list")) %>");
Why is there NO tutorial, code example or anything clear about the ajax thingy in rails3?
I had to use code parts from 5 different blogs, forums and casts, and mix them all together until I find the right combination... sigh
on repecmps lines,
just insert :content_type to represent part of content downloaded, like this:
format.js { render :layout=>false, :content_type => 'application/javascript' }
with complete part of repecmps responses:
def destroy
Product.find(params[:id]).destroy
#products = Product.all
respond_to do |format|
format.js { render :layout=>false, :content_type => 'application/javascript' }
end
end
/app/views/products/destroy.js.erb:
$("product_list").html("<%= escape_javascript(render(:partial => "list")) %>");
and, I found this to night.
I think your destroy action is doing too much, as it is destroying the product and list all the products. You could do something like:
/app/controllers/products.rb
class ProductsController < ApplicationController
respond_to :html, :js
def destroy
#product_id = params[:id]
Product.find(#product_id).destroy
respond_with do |format|
format.html { redirect_to posts_path }
end
end
end
/app/views/products/destroy.js.erb
$("#product_<%= #product_id %>").remove()
As long as your product element in the index uses something like dom_id, here's an example:
<ul id="products">
<% #products.each do |product|
<li id=<%= dom_id product %>>...</li>
<% end %>
</ul>
This way your destroy action will only destroy the intended product, and if the client has no JS it fallback the HTML request which will redirect to the products index which will be updated accordingly.
Hum... I'm going to try to help you.
Are you sure after clicking on the delete link, the request is handled as JS ?
Check on the log.
Is you file "app/views/products/destroy.rjs" is rendered ?
Rjs doesn't exist anymore in rails3. The new name is UJS.
Try to rename the file to destroy.js.{haml or erb}
Is it better ?

Resources