继承Phoenix / Elixir

时间:2016-09-16 03:41:49

标签: elixir phoenix-framework

我需要为Phoenix / Elixir应用程序创建一个简单的布局层次结构,并从不同的布局继承我的模板。我知道如何为单个布局和多个模板做到这一点。但是我怎样才能从另一个布局继承一个布局呢?

说,层次结构是layout1 - > layout2 - > layout3和template2(layout2),template3(layout3)。

在文档中没有提到这一点。

更新

基本布局是基本布局 - 类似于OOP中的基类,它不知道它的子布局 - 有多少,如果有的话。因此,从基础中调用“render children1”是没有意义的。

2 个答案:

答案 0 :(得分:2)

可以通过在调用render时在layout中传递assigns键来嵌套布局:

<%= render @view_module, @view_template, Map.put(assigns, :layout, {MyApp.LayoutView, "nested.html"}) %>

以下是Phoenix.View.render/3

文档中的相关部分
  

分配

     

分配意味着将是用户数据   可在模板中使用。然而,有分配的钥匙   由凤凰专门处理,他们是:

     
      
  • :layout - 告诉Phoenix将渲染结果包装成   给定布局。见下一节。
  •   
     

以下分配是保留的,不能直接设置:

     
      
  • @view_module - 正在呈现的视图模块
  •   
  • @view_template - 正在呈现的@view_module模板## Layouts模板可以使用:layout选项在其他模板中呈现。 :layout接受形式为元组的元组   {LayoutModule, "template.extension"}
  •   
     

渲染模板   在布局中,只需使用render/3拨打@view_module即可   并@view_template指定:

  <%= render @view_module, @view_template, assigns %>

对于3种布局,您可以执行以下操作:

# Controller
render(conn, "index.html", nested_1: "nested_1.html", nested_2: "nested_2.html")

# app.html.eex
<%= render @view_module, @view_template, Map.put(assigns, :layout, {MyApp.LayoutView, assigns.nested_1}) %>

# nested_1.html.eex
<%= render @view_module, @view_template, Map.put(assigns, :layout, {MyApp.LayoutView, assigns.nested_2}) %>

# nested_2.html.eex
<%= render @view_module, @view_template, assigns %>

答案 1 :(得分:2)

我解决这个问题的方法是在View中添加一个帮助器来渲染父布局:

defmodule MyApp.LayoutView do
  use MyApp.Web, :view

  def base_layout(conn, opts, do: contents) when is_list(opts) do
    render "base.html", [conn: conn, contents: contents] ++ opts
  end
end

&#34;内容&#34;帮助器中的参数将是您放在do / end块中的任何内容,因此您可以在HTML中使用它来进行&#34;子布局&#34;像:

<%= base_layout @conn, [foo: "bar"] do %>

    <div class="sublayout-wrapper">
      <%= render @view_module, @view_template, assigns %>      
    </div>
    <!-- specific footer for sub-layout goes here etc -->

<% end %>

在base.html布局中,我输出@contents变量,我需要在其中呈现内容,例如:

<html>
<head>
    <title>My App</title>
</head>
<body>
    <div class="header"></div>
    <%= @contents %>
</body>

这有点像黑客,但到目前为止,这是我发现问题的最佳解决方案。

请注意,我还添加了opts参数,以便能够在特定情况下覆盖某些分配(我主要使用此参数来定义要附加在<html><body>上的html css类取决于正在渲染的子布局。