I have read multiple tutorials where a partial is rendered as render #products, and then if you ajax a form for a new product, in the .js file you can do a render #product render the new product on the page.
However this only works if the view folder you are working in is called products, else you have to render the partial via render :partial => 'product', :collection => #products. Then when I want to ajax a form, I am unable to just append the new product with render :partial => 'product', :collection => #product. I have to clear the div and render all of the products again.
Is there a way to just render the new product, rather than having to clear and re-render all of the products when not working in a view folder with the same name as the model?
So in my controller, I had to add
class PostController < ApplicationController
respond_to :html, :js
then
def add
#post = Post.new(params[:post])
if #post.save
respond_with(#post, request.referer)
Then I had to make sure I had add.js.erb in my app/views/post, and in the js render the partial like render :partial => 'public/post, :object => #post
Related
I want to render a few instances of Post object on a single page.
Currently I have in my controller the code:
#post = Post.find(1)
and in the index view I have:
<%= render :partial => 'posts/post', :object => Post.find(1) %>
Now I want to print the second instance, how to do it? This code for the second instance does not work.
<%= render :partial => 'posts/post', :object => Post.find(2) %>
Couple of things:
When you set instance variable (prefixed with #) in your controller, they're available in your views. So you could do something like:
<%= render :partial => 'posts/post', :object => #post %>
Generally, index actions are meant to deal with a collection (#posts). I'd expect something like:
#posts = Post.where(author: current_user)
If you want to display a post identified by an id, I'd recommend taking a look at CRUD operations: https://guides.rubyonrails.org/routing.html#resources-on-the-web
Roughly, what you may want to do is something like:
# config/routes.rb
resources :posts
# app/controllers/posts_controller.rb
def show
#post = Post.find(params[:id])
end
# app/views/posts/show.html.erb
<%= render partial: 'posts/post', locals: { post: #post } %>
Remember that controllers sets the instance variables, and views use them
I'm rendering a partial that renders a form, using ajax (I can't just render the form directly). Posting a comment works fine when I'm rendering the form without ajax but with ajax it seems the partial can't access the #post variable.
<%= link_to "Render form", submit_comment_path, :remote => true %>
<div id="form">
</div>
I have a submit_comment.js file that looks like this:
$("#form").html("<%= j render(partial: 'comment_partial', locals: {post: #post}) %>");
The comment_partial view:
<%= render 'comments/form' %>
The form view:
<%= simple_form_for [post, Comment.new] %>
...
The submit_comment_path route:
get '/submit_comment', to: 'posts#submit_comment', as: :submit_comment
The posts controller (it's being rendered on the show page):
def show
#post = Post.find(params[:id])
end
def submit_comment
respond_to do |format|
format.html
format.js
end
end
and the comments controller:
def create
#post = Post.find(params[:post_id])
end
If I try to post a new comment it gives me a routing error and takes me to /posts//comment. Putting post.id in the comment_partial gives me an undefined error.
The big piece of the puzzle is understanding that instance variables (#post in this instance) disappear as soon as the Controller renders anything.
You correctly assign #post when you render the show page:
def show
#post = Post.find(params[:id])
end
However, #post disappears the second that show.html.erb is done rendering. When you click on the link to hit the submit comment method, no #post is getting created...
def submit_comment
# No instance variables here! :(
respond_to do |format|
format.html
format.js
end
end
Which means that the submit_comment.js file has no idea which post to be generating a form for.
However, it's not as simple as just throwing another Post.find(params[:id]) into the submit_comment method. You need to:
Define a route that relies on post id
Change the link in show.html.erb to include a specific #post.id
Then find the corresponding post to create a comment for.
It might look something like this...
routes.rb
...
resources :posts do
member do
get 'submit_comment'
end
end
...
Read up on member routes at the Rails Guide. There are other ways of accomplishing a similar route.
posts/show.html.erb
<%= link_to "Render form", submit_comment_post_url(#post), :remote => true %>
Note that the Rails default url helper is different than the one you've got, if you use member routes.
posts_controller.rb
def submit_comment
#post = Post.find(params[:id])
...
end
Hope that helps! Happy form-ing!
I have a simple partial to show some topics from the associated community
<%= render :partial => 'shared/topic', :collection => #community.topics %>
I'm trying to make a mobile version of the site, and to not render the partial to the same view, but to a new view.
I tried something like this
def topicsCommunity
fetch_topics ["community_id = ?", #community.id]
render :action => 'index'
end
But I can't get the community.id from my community view.
Also tried this :
#topicscommunity = #community.topics.find(:all,
:conditions => {:community_id => #community.id})
But from the topics_Controller, it didn't work.
Thanks for the help.
You don't have to use render :partial => ... in views only. You can easily do it in your controller (instead of render :action => ... or whatever).
So, just put this in the end of your controller
render :partial => 'shared/topic', :collection => #community.topics
There's no fundamental difference between calling render with :action, :partial, :text, :template or any other hash key.
If you just want to render the same template, use:
def topicsCommunity
fetch_skills ["community_id = ?", #community.id]
render 'index'
end
Here's the flow I have...
First, jquery posts the new comment to the server:
$.post(this.action,$(this).serialize(),null,'script');
Then in the comments controller:
def create
#comment = lots of stuff going on here but it works...
if #comment.save
flash[:notice] = "Successfully created comment."
respond_to do |format|
format.js
end
end
Ok and this is where I'm stuck, then the create.js.erb:
$(".cmtBox").html("<%=escape_javascript(render :partial =>"comments/comment")%>");
And the partial:
<div class="cmtBox" id="comment_<%=comment.id%>">
<%=comment.content%>
</div>
Where I'm stuck is calling the partial in create.js.erb... How do I pass what Rails needs to populate the partial? Right now I get the error: "Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id"
Thanks!
You should use:
render :partial => #comment
or
render :partial => "comments/comment", :object => #comment
or
render :partial => "comments/comment", :locals => {:comment => #comment}
I am building a fairly simple recipe app to learn RoR, and I am attempting to allow a user to save a recipe by clicking a link rather than through a form, so I am connecting the user_recipe controllers 'create' function through a link_to.
Unfortunately, for some reason the link_to is calling the index function rather than the create.
I've written the link_to as
<%= "save this recipe", :action => 'create', :recipe_id => #recipe %>
this link is on the user_recipes/index.html.erb and is calling the 'create' function of the same controller. It doesn't seem to make a difference if I include the :controller or not.
The controllers look like this
def index
#recipe = params[:recipe_id]
#user_recipes = UserRecipes.all # change to find when more than one user in db
respond_to do |format|
format.html #index.html.erb
format.xml { render :xml => #recipes }
end
end
def create
#user_recipe = UserRecipe.new
#user_recipe.recipe_id = params[:recipe_id]
#user_recipe.user_id = current_user
respond_to do |format|
if #menu_recipe.save
format.html { redirect_to(r, :notice => 'Menu was successfully created.') }
format.xml { render :xml => #menu, :status => :created, :location => #menu }
else
format.html { render :action => "new" }
format.xml { render :xml => #menu.errors, :status => :unprocessable_entity }
end
end
In the standard REST scheme the index action and the create action both have the same url (/recipes) and only differ in that index is accessed using GET and create is accessed using POST. So link_to :action => :create will simply generate a link to /recipes which will cause the browser to perform a GET request for /recipes when clicked and thus invoke the index action.
To invoke the create action use link_to {:action => :create}, :method => :post, telling link_to explicitly that you want a post request, or use a form with a submit button rather than a link.
Assuming you have default resources set up in your routes file, i.e. something like this
resources :recipes
The following will generate a link that will create a recipe; i.e. will be routed to the create action.
<%= link_to "Create Recipe", recipes_path, :method => :post %>
For this to work, JS needs to be enabled in your browser.
The following will generate a link that will show all recipes; i.e. will be routed to the index action.
<%= link_to "All Recipes", recipes_path %>
This assumes the default which is a Get HTTP request.