marick
August 3, 2016, 6:00pm
1
How should one write a view function that produces nested HTML, such as the safe version of:
I have a <strong>strong</strong> opinion.
The following works:
def strong_opinion do
shout = content_tag(:strong, "strong")
Phoenix.HTML.raw "I have a #{safe_to_string shout} opinion."
end
But the safe_to_string
then raw
sequence seems awkward. Is that the right way to do it?
You can use the ~E
sigil, that allows you to inject eex template inline:
def strong_opinion do
~E"""
I have a <%= content_tag :strong, "strong" %> opinion.
"""
end
8 Likes
marick
August 12, 2016, 10:16pm
3
I today realized that Phoenix rendering doesn’t work with strings, but rather with Erlang iolists . That means an invocation like:
<%= shout %>
… works when shout
is defined like this:
def shout do
["I have a ", content_tag(:strong, "strong"), " opinion"]
end
So building nested structures is surprisingly easy, including special handling of empty children:
def wrap_in_section(iolist) when length(iolist) == 0, do: []
def wrap_in_section(iolist) do
[tag(:hr),
content_tag(:p, iolist, class: "lead")]
end
Yep, eex’s are very simple, it is basically a compiled pre-made iolist that has a few bits of its filled in at render time, it is very fast, and functional.