【问题标题】:Rails view rendering nested layouts - named yield not working while unnamed yield does workRails 视图渲染嵌套布局 - 命名的 yield 不起作用,而未命名的 yield 起作用
【发布时间】:2018-08-26 18:00:10
【问题描述】:

非工作代码:

# application.html.erb, BASE layout
<html>
<head>
<body>
<%= yield %>
</body>
</head>
</html>

# _pwa.html.erb, SPECIFIC layout
<div class="container">
  <%= yield :main_content %>
</div>

# _partial.html.erb, ACTUAL body
<% content_for :main_content do %>
  <h1>Test</h1>
<% end %>

# view.html.erb, actual view file that links everything together
<%= render layout: "layouts/pwa" do %>
  <%= render "partial" %>
<% end %>

view.html.erb 被控制器渲染时,我希望输出的 html 文件看起来像这样:

<html>
<head>
<body>
  <div class="container">
    <h1>Test</h1>
  </div>
</body>
</head>
</html>

&lt;h1&gt;Test&lt;/h1&gt; 实际上并不存在。另一方面,如果我删除命名的产量,并用常规产量替换,它确实有效。即,下面的代码确实生成了上面的正确输出:

工作代码:

# application.html.erb, BASE layout
<html>
<head>
<body>
<%= yield %>
</body>
</head>
</html>

# _pwa.html.erb, SPECIFIC layout
<div class="container">
  <%= yield %>
</div>

# _partial.html.erb, ACTUAL body
<h1>Test</h1>

# view.html.erb, actual view file that links everything together
<%= render layout: "layouts/pwa" do %>
  <%= render "partial" %>
<% end %>

但我确实想弄清楚如何让命名区域工作,因为实际的 pwa 布局有点复杂,我想做如下的事情:

# _pwa.html.erb
<div class="container">
  <%= yield :main_content %>
</div>
<div class="container">
  <%= yield :secondary_content %>
</div>

# _partial.html.erb
<% content_for :main_content do %>
  <h1>Test</h1>
<% end %>
<% content_for :secondary_content do %>
  <h2>Second</h2>
<% end %>

编辑,我实际上有一个像这样的迭代器:

<%= render layout: "layouts/pwa" do %>
  <% @pages.each do |p| %>
    <%= render "partial/#{p}" %>
  <% end %>
<% end %>

【问题讨论】:

  • 确保 content_for 对象在调用之前被创建。
  • 更改位置 yield 和 content_for
  • 谢谢!不知道你们是什么意思,content_foryield 所以不知道如何进行任何位置更改以确保在 yield 之前创建 content_for 对象
  • @james,试试这个:render partial: 'partial', layout: 'layouts/pwa'
  • 啊,好吧,我这里有一些隐藏的上下文,我实际上有一个迭代器(见上面的编辑),这就是为什么我真的不想那样做,因为那样布局被多次渲染。 @fongfan999 我想知道为什么命名的收益不起作用,但非命名的收益确实有效?

标签: ruby-on-rails view rendering yield


【解决方案1】:

感谢您的反馈!我最终做的是下面。这样就完成了:

  1. 在 X 页面没有重定向(即 JS 隐藏/显示内容模拟从一个页面移动到另一个页面)的网站上具有渐进式“应用程序”的感觉。我认为这是最难的部分,因为它破坏了 MVC……但在我的情况下是一个重要的权衡
  2. 为所有 X 页面呈现了一个单一布局,但此布局上的某些内容会因我们所在的页面而异
  3. X 页面上的内容可以在 Y 页面的其他渐进式流程中进一步共享

查看文件层次结构

> views
  > layouts
    - _pwa.html.erb # single layout for all steps
  > orders
    > optionA
      - _place_A.html.erb # unique content for a shared view file that is further shared across options
      - flow_layout.html.erb # iterator that pulls in views from the various pages relevant to this option from shared_views folder

    > optionB
      - _place_B.html.erb # unique content for a shared view file that is further shared across options
      - flow_layout.html.erb # iterator that pulls in views from the various pages relevant to this option from shared_views folder
    > shared_views
      > views
        - _open.html.erb # unique content for a given page
        - _place_A.html.erb # unique content for a given page
        - _place_B.html.erb # unique content for a given page
      > layouts
        - _place.html.erb # similar content for a page that's different than other pages (i.e., open and place are different pages), but with elements shared across options (i.e., place_A and place_B have a lot of sharing)

代码

<!-- shared layout file: layouts/_pwa.html.erb -->
<%= render "/layouts/navbar", progress_counter: @pages.count %>
<div class="container-fluid zero-padding  non-navbar">
  <div class="row-fluid "> 
    <%= yield %> <!-- main content, varies for each of X pages -->
  </div>
  <div class="row-fluid troubleshooter_title">
    <div class="col-xs-12">
      <h4 class="cursor-point underline text-center">
        <span class="glyphicon glyphicon-menu-right"></span> <%= troubleshooter_title %> <!-- named content varies for each of X pages -->
      </h4>
    </div>
  </div>
  <%= yield :troubleshooter_content %> <!-- named content varies for each of X pages -->
</div>

# Orders Controller file for 2 set of steps (optionA vs optionB)
# as implied below, "place_A" and "place_B" are VERY similar, with a few tweaks
def optionA
  # second element of inner array stores other info not relevant to this answer here
  @pages = [
    ["open"],
    ["place_A"],
  ]
  render "#{action_name}/flow_layout"
end

def optionB
  @pages = [
    ["place_B"],
  ]
  render "#{action_name}/flow_layout"
end

<!-- flow_layout as rendered by controller -->

<!-- optionA/flow_layout.html.erb -->
<%= render layout: "layouts/pwa", locals: {troubleshooter_title: "Having trouble?" } do %>
  <% @pages.each do |p| %>
    <%= render "shared_views/views/#{p[0]}" %> 
  <% end %>
<% end %>

<!-- optionA/flow_layout.html.erb -->
<%= render layout: "layouts/pwa", locals: {troubleshooter_title: "How it works" } do %>
  <% @pages.each do |p| %>
    <%= render "shared_views/views/#{p[0]}" %> 
  <% end %>
<% end %>

<!-- above note one important fact, I wanted the troubleshooter_title to CHANGE between optionA & optionB -->


<!-- shared_view partials -->
<!-- shared_views/views/_open.html.erb -->
<!-- first div goes into main yield -->
<div class="col-xs-12">
  <h1>Open the door</h1>
</div>
<% content_for :troubleshooter_content do %>
  Try pushing instead of pulling
<% end %>

<!-- shared_views/views/_place_A.html.erb -->
<!-- given the fact that place_A and place_B are very similar, there's a nesting here of a place layout file that holds all the commonalities. the minor differences are placed with the optionA view folder itself -->
<%= render layout: "shared_views/layouts/place" do %>
  <%= render "optionA/place_A" %>
<% end %>

<!-- shared_views/views/_place_B.html.erb -->
<!-- same as above -->
<%= render layout: "shared_views/layouts/place" do %>
  <%= render "optionB/place_B" %>
<% end %>

<!-- place layout -->
<div class="col-xs-12">
  <h1><%= yield %></h1>
</div>
<% content_for :troubleshooter_content do %>
  <%= yield :nested_troubleshooter_content %>
<% end %>

<!-- optionA/_place_A.html.erb -->
Place A: put on table
<% content_for :nested_troubleshooter_content %>
  Table is directly in front of you 
<% end %>

<!-- optionB/_place_B.html.erb -->
Place B: put on rug
<% content_for :nested_troubleshooter_content %>
  Rug is to the right of you 
<% end %>

【讨论】:

    猜你喜欢
    • 2014-11-17
    • 2021-06-06
    • 2013-11-13
    • 2014-10-14
    • 2021-03-29
    • 2017-11-18
    • 2018-06-08
    • 2018-07-08
    • 1970-01-01
    相关资源
    最近更新 更多