Phoenix - 模板中的组详细信息项

Phoenix - Group detail items in a Template

鉴于以下情况:

[
  {"2016-05-06T08:59:50", "Woke up"},
  {"2016-05-06T09:30:20", "Ate breakfast"},
  {"2016-05-07T01:48:10", "Went to bed"}
]

我想在网页中显示(以上)详细信息行,但按天分组:

<h1>6 May 2016</h1>
8:59 - Woke up
9:30 - Ate breakfast

<h1>7 May 2016</h1>
1:48 - Went to bed

在 Phoenix 中,使用模板执行此操作的最佳方法是什么?在模板中呈现之前,最好将 Ecto 查询的结果转换为控制器中的 parent/child 数据结构吗?如果是这样,我会在模板中使用嵌套循环吗?

您可以使用 Enum.group_by/3:

对日期进行分组
Enum.group_by(dates, fn {date, _} -> Ecto.Date.cast!(date) end)

结果如下:

%{#Ecto.Date<2016-05-06> => [{"2016-05-06T09:30:20", "Ate breakfast"},
  {"2016-05-06T08:59:50", "Woke up"}],
  #Ecto.Date<2016-05-07> => [{"2016-05-07T01:48:10", "Went to bed"}]}

但是,地图不是有序数据类型,因此您可能应该在使用 Enum.sort/1:

之后对它们进行排序
Enum.group_by(dates, fn {date, _} -> Ecto.Date.cast!(date) end) |> Enum.sort()

[{#Ecto.Date<2016-05-06>,
  [{"2016-05-06T09:30:20", "Ate breakfast"},
   {"2016-05-06T08:59:50", "Woke up"}]},
 {#Ecto.Date<2016-05-07>, [{"2016-05-07T01:48:10", "Went to bed"}]}]

您的模板应该类似于:

<%= for {date, events} <- @dates do %>
  <h1><%= date %></h1>
  <%= for event <- Enum.reverse(events) do %>
    <%= event %>
  <% end %>
<% end %>

注意我们在这里颠倒了列表,这是因为group_by将通过将头部添加到列表来构建列表。