Phoenix HTML guidelines
- •
Phoenix templates always use
~Hor .html.heex files (known as HEEx), never use~E - •
Always use the imported
Phoenix.Component.form/1andPhoenix.Component.inputs_for/1function to build forms. Never usePhoenix.HTML.form_fororPhoenix.HTML.inputs_foras they are outdated - •
When building forms always use the already imported
Phoenix.Component.to_form/2(assign(socket, form: to_form(...))and<.form for={@form} id="msg-form">), then access those forms in the template via@form[:field] - •
Always add unique DOM IDs to key elements (like forms, buttons, etc) when writing templates, these IDs can later be used in tests (
<.form for={@form} id="product-form">) - •
For "app wide" template imports, you can import/alias into the
my_app_web.ex'shtml_helpersblock, so they will be available to all LiveViews, LiveComponent's, and all modules that douse MyAppWeb, :html(replace "my_app" by the actual app name) - •
Elixir supports
if/elsebut **does NOT supportif/else iforif/elsif. Never useelse iforelseifin Elixir, always usecondorcasefor multiple conditionals.Never do this (invalid):
code<%= if condition do %> ... <% else if other_condition %> ... <% end %>
Instead always do this:
code<%= cond do %> <% condition -> %> ... <% condition2 -> %> ... <% true -> %> ... <% end %> - •
HEEx require special tag annotation if you want to insert literal curly's like
{or}. If you want to show a textual code snippet on the page in a<pre>or<code>block you must annotate the parent tag withphx-no-curly-interpolation:code<code phx-no-curly-interpolation> let obj = {key: "val"} </code>Within
phx-no-curly-interpolationannotated tags, you can use{and}without escaping them, and dynamic Elixir expressions can still be used with<%= ... %>syntax - •
HEEx class attrs support lists, but you must always use list
[...]syntax. You can use the class list syntax to conditionally add classes, always do this for multiple class values:code<a class={[ "px-2 text-white", @some_flag && "py-5", if(@other_condition, do: "border-red-500", else: "border-blue-100"), ... ]}>Text</a>and always wrap
if's inside{...}expressions with parens, like done above (if(@other_condition, do: "...", else: "..."))and never do this, since it's invalid (note the missing
[and]):code<a class={ "px-2 text-white", @some_flag && "py-5" }> ... => Raises compile syntax error on invalid HEEx attr syntax - •
Never use
<% Enum.each %>or non-for comprehensions for generating template content, instead always use<%= for item <- @collection do %> - •
HEEx HTML comments use
<%!-- comment --%>. Always use the HEEx HTML comment syntax for template comments (<%!-- comment --%>) - •
HEEx allows interpolation via
{...}and<%= ... %>, but the<%= %>only works within tag bodies. Always use the{...}syntax for interpolation within tag attributes, and for interpolation of values within tag bodies. Always interpolate block constructs (if, cond, case, for) within tag bodies using<%= ... %>.Always do this:
code<div id={@id}> {@my_assign} <%= if @some_block_condition do %> {@another_assign} <% end %> </div>and Never do this – the program will terminate with a syntax error:
code<%!-- THIS IS INVALID NEVER EVER DO THIS --%> <div id="<%= @invalid_interpolation %>"> {if @invalid_block_construct do} {end} </div>