2013-12-09 57 views
8

我无法找到一种方法,做到以下几点:轨道4嵌套布局

让我application.html.erb说我有以下

<div id="one" > 
    <%= yield %> 
</div> 

然后我想有另一个布局文件asdf.html.erb

<div id="two"> 
    <%= yield %> 
</div> 

我想最终的输出是

<div id="one> 
    <div id="two"> 
     <%= yield %> 
    </div> 
</div> 

可能吗?谢谢。

回答

7

默认情况下,application.html.erb是你的布局。

# app/views/layouts/application.html.erb 
<div id="one" > 
    <%= render "layouts/asdf" %> 
</div> 

# app/views/layouts/_asdf.html.erb 
<div id="two"> 
    <%= yield %> 
</div> 

这将输出如下:

<div id="one> 
    <div id="two"> 
     <%= yield %> 
    </div> 
</div> 

或者,如果你正在寻找你可以通过调用它作为一个局部,从您的应用程序布局呈现默认子布局有条件地以控制器为基础呈现布局,您应该考虑使用nested layouts。从文档:

论NewsController生成的页面,你要隐藏的顶部菜单,然后添加一个右键菜单:

# app/views/layouts/news.html.erb 
<% content_for :stylesheets do %> 
    #top_menu {display: none} 
    #right_menu {float: right; background-color: yellow; color: black} 
<% end %> 
<% content_for :content do %> 
    <div id="right_menu">Right menu items here</div> 
    <%= content_for?(:news_content) ? yield(:news_content) : yield %> 
<% end %> 
<%= render template: "layouts/application" %> 

新闻观点将使用新的布局,隐藏顶部菜单并在“内容”div中添加新的右侧菜单。

+0

但是如何获得被调用的布局的名称?我期望'layout =='application'?产量:渲染布局“ –

8

我迄今为止发现的干净的解决方案来自这个回购:https://github.com/rwz/nestive

我不想整个宝石。如果你像我一样,这里就是我实现我想要的东西:

# application_helper.rb 

    # From https://github.com/rwz/nestive/blob/master/lib/nestive/layout_helper.rb 
    def extends(layout, &block) 
    # Make sure it's a string 
    layout = layout.to_s 

    # If there's no directory component, presume a plain layout name 
    layout = "layouts/#{layout}" unless layout.include?('/') 

    # Capture the content to be placed inside the extended layout 
    @view_flow.get(:layout).replace capture(&block) 

    render file: layout 
    end 

然后你继续/layouts/application.html.erb不变!

而且您可以创建其他布局。在我的情况/layouts/public.html.erb/layouts/devise.html.erb

# public.html.erb 
<%= extends :application do %> 
    <%= render 'partials/navbar' %> 
    <div class="container margin-top"> 
    <%= yield %> 
    </div> 
<% end %> 

# devise.html.erb 
<%= extends :public do %> 
    <div class="col-sm-6 col-sm-offset-3"> 
    <%= yield %> 
    </div> 
<% end %> 

就像一个魅力!我仍然在微笑着,终于找到了一个干净的解决方案

+0

今天发现您的评论,并立即使用它。这非常有用,谢谢! – dimitarvp

1

您也可以执行以下操作来有条件地呈现子布局:

# app/views/layouts/application.html.erb 
<%= controller.controller_name.include?("foo") ? render("layouts/foo") : yield %> 

# app/views/layouts/_foo.html.erb 
<div class="bar"> 
    <%= yield %> 
</div> 

对于只有一个子布局的情况,我觉得这是最好的Rails guide,因为执行中列出的嵌套布局方法不必从子布局转到主布局,然后返回到子布局。相反,它更自然地流动,从主布局开始,进入子布局,然后在视图结束。

0

如果你正在寻找一个干净的解决方案,它不夫妇application.html.erb其继承元素,宝石nestive(如在其他指出的使用要做到这一点,但它似乎没有工作使用Rails 5.但是,这是另一种方式来做到这一点:https://mattbrictson.com/easier-nested-layouts-in-rails

# Place this in app/helpers/layouts_helper.rb 
module LayoutsHelper 
    def parent_layout(layout) 
    @view_flow.set(:layout, output_buffer) 
    output = render(:file => "layouts/#{layout}") 
    self.output_buffer = ActionView::OutputBuffer.new(output) 
    end 
end 

然后asdf.html.erb成为

<div id="two"> 
    <%= yield %> 
</div> 
<% parent_layout 'application' %> 

被警告,这依赖于Rails内部,它可能会停止在未来版本中此工作不太可能很快发生,因为它至少已经工作了3年(根据链接的博客文章的日期)。