Have a post with comments. On post/show, when a user clicks the add comment button the server calls a javascript function that should add the new comment action as a partial:
render 'comments/new'
$("#newcomment").live("click",function() { $("#addcomment").load("<%= url_for :controller => 'comments', :action => 'new', :locals => {:parent_id => #post.parent_id} %>")
def new
#comment = Comment.new( :parent_id => params[:parent_id] )
render :partial => "form", :layout => false
end
new view:
render "form" # form is the add comment form
The problem is that the local variables are not passed and I can't add the comment (it wont call create)
render * never call an action in a controller, even render :action => 'edit'! It generates only the corresponding partial in every case. It may sometimes be confusing.
What you cand do to solve your probelm quickly is to call your partial via an ajax call.
In your views :
<div id="new_comment"></div>
In your controller :
render :update do
replace 'news_comment', partial => 'comments/new'
end
Hope this help.
Related
I have a Rails app where on the home page home/index.html.erb, I show a partial for the model workorders. It currently defaults to the home_controleer.rb with the action index.
Can I select the workorders_controller.rb and action index2?
I tried this in the home/index.html.erb view file:
<%= render :partial => "workorders/index7", :controller => "workorders", :action => "index2" %>
But it's not working.
Try this instead:
<%= render :template => "workorders/index2" %>
source: https://stackoverflow.com/a/6051812/2128691
edit: in response to your last comment...
I haven't really worked with bootstrap, but maybe you could do something like this [pseudocode]:
def home
if [x condition]
redirect_to index_seven_path
else
render :action => [y action]
end
end
Here is the API definition for render:
render(options = {}, locals = {}, &block)
Returns the result of a render that’s dictated by the options hash. The primary options are:
:partial - See ActionView::Partials.
:file - Renders an explicit template file (this used to be the old default), add :locals to pass in those.
:inline - Renders an inline template similar to how it’s done in the controller.
:text - Renders the text passed in out.
There is no explanation about what's the purpose of locals here? What's locals for?
Thanks.
To pass local variables to the partial template, as opposed to controller instance variables.
See Section 3.4.4, Passing Local Variables in the Layouts and Rendering Guide.
For example:
<%= render :partial => "account" %>
This means there is already an instance variable called #account for the partial and you pass it to the partial.
<%= render :partial => "account", :locals => { :account => #buyer } %>
This means you pass a local instance variable called #buyer to the account partial and the variable in the account partial is called #account. I.e., the hash { :account => #buyer } for :locals is just used for passing the local variable to the partial. You can also use the keyword as in the same way:
<%= render :partial => "contract", :as => :agreement
which is the same as:
<%= render :partial => "contract", :locals => { :agreement => #contract }
I've seen the other posts, but can't seem to figure out why this isn't working for me
In my controller I set
#referrer=referrer.name
in my view i have
<%= render 'js', :referrer => #referrer >
then in my partial i put
var type =' <%= referrer >';
I get a response 'undefined local variable or method 'referrer' and it points to the _js file.
from what I can see, this is exactly how it is supposed to be written, what am I doing wrong?
<%= render :partial => "account", :locals => { :referrer => #referrer } %>
Your variables to use in the partial need to be passed via the :locals hash.
Reference: http://api.rubyonrails.org/classes/ActionView/Partials.html
EDIT
The following works perfectly for me:
Controller:
def index
#referrer = "test"
end
index.html.erb
<%= render :partial => "account", :locals => { :referrer => #referrer } %>
_account.html.erb
<%=referrer%>
Turns out the reason was that in the partial, I had to call
var type='<%= #referrer %>'
not sure why all the other documentation i'd seen had it without the # symbol
I am calling:
render #users, :layout => "homepage"
because I want to wrap the default partial for users (views/_user.html.erb) with a custom layout just for the homepage (views/users/_homepage.html.erb).
but, when I do this, I get the NoMethodError on the user.name method.
For some reason it seems like the user variable is not getting initialized properly inside the user partial.
It turns out after some test, the homepage partial is not even getting called, it is going straight to the user partial ....
This is not the solution I wanted, I believe there may actually be a way to make this work using just a call to render, but this is what gave me the correct output:
#users.each do |user|
render :partial => "users/user",
:layout => "users/homepage",
:locals => { :user => user }
end
Or is it that the :layout option only works when rendering a single resource and not a collection?
As of Sept. 2019, in Rails 6, this is how we are doing this:
<%= render partial: 'homepage_user_list_entry', collection: #users %>
With alias:
<%= render partial: 'homepage_user_list_entry', collection: #banned_users, as: :user %>
Hope this helps future searchers, and also me in the future.
Try adding :as => :user to render a partial from a view:
<%= render :collection => #users, :as => :user, :partial => 'users/user_short_form', %>
You should do something like
<%= render 'homepage', :collection => #users, :layout => 'homepage' %>
not sure about the :layout option, but you have to pass #users thro :collection
hope it helps!
Not sure if this is a newer addition to Rails, but in Rails 4.2.1 I can pass my collection to the partial argument of render:
render partial: #users, layout: "homepage"
So I've got a form in my Rails app which uses a custom FormBuilder to give me some custom field tags
<% form_for :staff_member, #staff_member, :builder => MyFormBuilder do |f| %>
[...]
<%= render :partial => "staff_members/forms/personal_details", :locals => {:f => f, :skill_groups => #skill_groups, :staff_member => #staff_member} %>
[...]
<% end %>
Now, this partial is in an area of the form which gets replaces by an AJAX callback. What I end up doing from the controller in response to the AJAX request is:
render :partial => "staff_members/forms/personal_details", :locals => {:skill_groups => #skill_groups, :staff_member => #staff_member}
However, if I do that then the form breaks, as the FormBuilder object I used in the form_for is no longer available. Is there any way for me to use my custom FormBuilder object inside a partial used for an AJAX callback?
Use fields_for inside your partial. It performs a similar task but without wrapping the form tags. See the API docs.
how about this?
#template.with_output_buffer do
#template.form_for #model_object do |f|
f.fields_for :some_nested_attributes do |ff|
render :partial => 'nested_attributes', :object => #model_object, :locals => {:form => ff}
end
end
end
this would be especially useful is you need to use the nested fields_for in the partial
You could instantiate a new instance of your form builder in the controller, though it feels sort of lousy to me:
# in the controller
render :partial => {
:f => MyFormBuilder.new(:staff_member, #staff_member, template),
:skill_groups => #skill_groups,
:staff_member => #staff_member
}
Alternatively, you could move more of the update logic to be client side which wouldn't require you to worry about rendering anything at all. You could just update the values via JS. Not sure if that works for your project though.
Maybe I'm a little late in the game here, and maybe I don't understand the question properly, but in ApplicationHelper.rb I think you can just add the line:
ActionView::Base.default_form_builder = MyFormBuilder
You can submit within your ajax call the content of f.object_name (it's also works with partials) and use it to render tags defined in http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html passing it as the first argument.