はじめに
前回はViewを見てきました。
今回はテンプレートです。
次回は、Channelになります。
鋳型
PhoenixのTemplateはpre-compiledなので速いです。
PhoenixのデフォルトのテンプレートシステムはEExです。EExでは、RouterやViewのようなファイル生成も行います。
テンプレートは、標準ではweb/templates
ディレクトリの下に、Viewの先頭部分と同じ名前のディレクトリを作り、そこに格納されます。
リスト表示
テンプレートで、文字列や数字を記述する例はいままで出てきましたが、リストの値を表示したい場合にはどうすればよいでしょうか。
答えは、Elixirの内包表現(Comprehension)を使うことです。
conn
に含まれるリストの全キーを表示する例を書いてみます。まずViewです。
defmodule HelloPhoenix.PageView do
use HelloPhoenix.Web, :view
def connection_keys(conn) do
conn
|> Map.from_struct()
|> Map.keys()
end
end
次にテンプレートを書いてみます。
<div class="jumbotron">
<p><%= handler_info @conn %></p>
<h3>Keys for the conn Struct</h3>
<%= for key <- connection_keys @conn do %>
<p><%= key %></p>
<% end %>
</div>
注意が必要なのは、何かを出力する場合は、常に、"<%= %>"を用いなければならないということです。何も出力する必要が無い場合は"<% %>"と"="は必要ありません。
テンプレートの中のテンプレート
上記の例でキーを表示するコードが"<%= key %>"と単純なのでいいですが、これが複雑になると可読性が著しく低下します。
解決方法として、キーを表示する部分を別のテンプレートにすることです。
キーを表示するテンプレートとして、web/templates/page/key.html.eex
を以下のように作成します。
<p><%= @key %></p>
ここで、key
を@key
にしているのは、呼び出しもとでrender関数のパラメータとして値を渡すためです。
@key
は実際には<%= {:ok, v} = Access.fetcch(assigns, :key); v %>
と変換されます。
上記で記述したTemplateは次のように変更します。
<div class="jumbotron">
<p><%= handler_info @conn %></p>
<h3>Keys for the conn Struct</h3>
<%= for key <- connection_keys @conn do %>
<%= render "key.html", key: key %>
<% end %>
</div>
View間でのTemplate共有
Templateを複数のViewで共有したいというケースはままあります。こういう場合、render関数に明示的にViewを指定することで、他のViewのTemplateを使用することができます。
例えば、先ほどの例でkey.html.eex
を複数のView間で共有したいとします。
まず共有用のViewを作成することにします(web/views/shared_view.ex
)。
defmodule HelloPhoenix.SharedView do
use HelloPhoenix.Web, :view
end
次に、このView用のTemplateディレクトリを作成します(web/templates/shared
)。そして、先ほどのkey.html.eex
をこのディレクトリに移動します。
後は、TemplateをこのViewとサブのTemplate用に変更します。
<%= for key <- connection_keys @conn do %>
<%= render HelloPhoenix.SharedView, "key.html", key: key %>
<% end %>