Rendering components from a view

I want to render a list of widgets where each one has a trailing static element, except the last

<div class="widget">
<br>
<div class="widget">
<br>
<div class="widget">

Comprehensions in templates make it a little tricky, so I wrote a recursive function to handle it from my view

# template.html.heex
<div class="flex flex-col space-y-2">
  <%= render_widgets(@widgets) %>
</div>
# my_view.ex
def render_widgets(widgets), do: widgets(widgets, []) |> Enum.reverse()

defp widgets([widget], acc), do: [do_render(widget) | acc]
defp widgets([widget | tail], acc) do: widgets(tail, [tag(:br), do_render(widget) | acc]

defp do_render(widget) do
  component(&widget/1, [])
  |> Phoenix.HTML.Safe.to_iodata()
  |> Phoenix.HTML.raw()
end

defp widget(assigns), do: ~H"<div class='widget'>Foo</div>"

Am I missing any change-tracking goodness (or something else?) by rendering my components this way?

1 Like

If this is the specific case, I feel like this would be better handled with CSS and margin.

The example case is a bit too simple—the trailing element will be another component, not a <br>

Enum.intersperse

See related posts: