I have a main layout (application) and two 'sub' layouts (dashboard and admin). In my dashboard and admin controllers respectively I have a before_filter which render templates: the template I want (either dashboard or admin).
In my dashboard and admin layouts, I am doing something along the lines of:
<% content_for :top_menu do %>
<%= render partial: "layouts/menu/top", locals: {section: 'admin'} %>
<%= render partial: "layouts/menu/sub", locals: {section: 'admin'} %>
<% end %>
So this is including the top partials with a section local which shows the correct options I want.
In my application layout, I have the following:
SOME HTML HERE
<%= yield :top_menu %>
SOME HTML HERE
<%= yield %>
SOME HTML HERE
The problem is that the content from my views isn't being displayed, I'd expect it to be displayed where the 'yield' is in my application layout.
I have read: http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts - but following that just displays the menus twice and still doesn't display my content.
I think I am failing to understand something here, help would be appreciated.
In short, I want top menus and it's in the controller that I want to specify which menu is to be used. I'm sure there is a better solution to this that I am missing also.
I have fixed this by doing:
layout 'menu/admin'
In my controller, and adding:
<%= render template: "layouts/application" %>
To my layouts.
Related
I've tried to make sense of layouts but got lost..Also googled & looked at other similar questions on SO but none of them helped.
Say I have MVC's (scaffold'ed) for A and B, creating their ..views/A/index.html.erb and ..views/B/show.html.erb among the rest.
A's index method sets a #a_collection.
Within B's show view I want to:
<p>..stuff for B..</p>
<%= render A's index %>
<p>..some more B-stuff</p>
How can I render A's index in that place in B's show?
You don't typically render a view inside of another view. You use partials to share code across views. For example:
# app/views/products/_product.html.erb
# this is the code you want to reuse
<p>Product Name: <%= product.name %></p>
# app/views/products/index.html.erb
<%= render #products %>
# app/views/stores/show.html.erb
<h1><%= #store.name %></h1>
<h2>Our Products</h2>
<%= render #store.products %>
<%= render #products %> is shorthand for <%= render partial: "product", collection: #products %>.
This is just the implicit rendering - in many cases you'll want to add more partials and render them explicitly. Like for example the _form.html.erb partial that you'll find in the scaffolds thats used to share a form between the create and edit views.
Think of partials like the view equivilent to a function - ideally they should take some input in the form of locals and result in a chunk of HTML.
In my quest to keep my application views as DRY as possible I've encountered a little snag. My appliation.html.erb incorporates a static sidebar menu. Each of my main controllers incorporates a secondary sidebar menu (essentially a submenu). I can take the code that renders the menu out of application.html.erb and put it in each of my views and change the secondary sidebar there, but this produces a lot repetition in my views.
I saw this SO post and looked at this page, but I was unable to get either idea to work. I was thinking that I could put something like:
<% provide(:submenu, 'layouts/sidebars/sidebar_customers_contacts') %>
at the top of each view and use that to render the associated partial by doing
<% content_for(:submenu) do %>
<%= render :partial => :submenu %>
<% end %>
from the application.html.erb but of course that didn't work.
This is my current application.html.erb:
<div class="side">
<%= render 'layouts/sidebar' %>
<%= render 'layouts/sidebars/sidebar_dashboard' %><!-- this needs to load a sidebar based on the controller that calls it. Each view of the controller will get the same sidebar. -->
</div>
<div class="main-content">
<%= yield %>
</div>
I feel like I'm making this more difficult than it really is. Is there a simple way to do this?
Rails provides a helper called controller_name which you can read more about here.
Assuming you adhere to your own naming conventions, this should work as-is. If you decide some controllers don't get a sidebar, you may need to throw in some conditionals...
application.html.erb
<div class="side">
<%= render "layouts/sidebar" %>
<%= render "layouts/sidebars/#{ controller_name }" %>
</div>
<div class="main-content">
<%= yield %>
</div>
EDIT
Sorry, my mistake was using single quotes instead of double-quotes. You cannot use #{string interpolation} within single quotes. Source
Im trying to bring a layout in my html page by
render layout 'flatty'
thing is this loads the whole flatty layout. In flatty.html.erb it renders _header,_footer and also _sidebar.html.erb
I dont want to load _sidebar.html.erb in this particular page.
So how should i render this?
thing is this loads the whole flatty layout. In flatty.html.erb it renders _header,_footer and also _sidebar.html.erb I dont want to load _sidebar.html.erb in this particular page
Why do you want to use same layout if you have so many changes? Why not make a partial which you could render in both cases. Make a new partial, lets say _common.html.erb, render it in your flatty layout and view of the action in which you want to use it.
#flatty.html.erb
<%= render "common" %>
<%= render "sidebar" %>
#some_action_name.html.erb
<%= render "common" %>
If you still want to use same layout in both cases then you ca use rails 4 controller_name and action_name helpers in your layout and selectively render sidebar and other partials in your layout:
#flatty.html.erb
<%= if controller_name == "some_controller_name" && action_name == "some_action_name"
<%= render "sidebar" %>
<% end %>
Maybe in your controller action, you can have a flag indicating the sidebar should not be rendered. Then, in your flatty.html.erb file, check for the flag variable before you render the _sidebar.html.erb.
For example, if you have a controller action called flatty, add an instance variable, #disable_sidebar, to act as your flag.
def flatty
#disable_sidebar = true
# Your other code
render layout: 'flatty'
end
Then, in your flatty.html.erb, add a conditional before your render for your sidebar (note the ! negation in the if statement:
<% if !#disable_sidebar %>
<%= render "layouts/sidebar" %>
<% end %>
Alternatively, in your flatty.html.erb you can also check for the controller and action values in your params hash, and then don't render your sidebar if it matches that controller's action:
<% if params[:controller]!="YOUR_CONTROLLER" and !params[:action].eql? "flatty" %>
<%= render "layouts/sidebar" %>
<% end %>
So I'm working on an open source project and due to different versions, there's the issue where I can't count on there being a controller for a view. Instead this email would be send out via a rake task for one version and a few others would done via a controller. Now you understand why I'm asking a bad practice question...
I have a layout for a view. Does anyone know a way to specify what the layout is for the view within the view. Some pseudo-code:
<%= extends 'layout/test_mailer` %>
<h1> Hey there! </h1>
And the layout would have the usual yield within it.
I hope I'm explaining the problem good enough.
<%= render partial: "hey_page", layout: "layout/test_mailer" %>
Check part 3.4.3 Partial Layouts at RailsGuides.
I think using yield and content_for should solve the problem. [Guides]
# my_layout.html.erb
<%= yield :mail_view %>
# my_mail_view.html.erb
<%= content_for :mail_view do %>
<!-- html -->
<% end %>
Of-course, if you are using params to get the layout, this would be a wrong answer.
Then, you can also use:
<%= render partial: "link_area", layout: "graybar" %>
You can use
//controller action
def index
render layout: test_mailer
end
//view, index.html.erb
<h1> Hey there! </h1>
//view, layout/test_mail.html.erb
<html>....layout for you test mail
<% yield %>
</html>
I am trying to add a "Create Account" box to the sidebar of my homepage. I added it to my application layout but I only want it to appear when the user is on my homepage. What is the best way to detect which page you are on and when to render the content?
<% if current_page? %>
<%= render layout/create_account %>
Thanks in advance
I would do it via content_for
In your sidebar insert this:
<%= yield :create_account_box %>
And then in your homepage view do this:
<% content_for :create_account_box do %>
render your box here.
<% end %>
This technique allows to inject content from subviews to superviews without any ifs or stuff like that.