usage-rules/html.md
Phoenix templates always use ~H or .html.heex files (known as HEEx), never use ~E
Always use the imported Phoenix.Component.form/1 and Phoenix.Component.inputs_for/1 function to build forms. Never use Phoenix.HTML.form_for or Phoenix.HTML.inputs_for as 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's html_helpers block, so they will be available to all LiveViews, LiveComponent's, and all modules that do use MyAppWeb, :html (replace "my_app" by the actual app name)
Elixir supports if/else but does NOT support if/else if or if/elsif. Never use else if or elseif in Elixir, always use cond or case for multiple conditionals.
Never do this (invalid):
<%= if condition do %>
...
<% else if other_condition %>
...
<% end %>
Instead always do this:
<%= 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 with phx-no-curly-interpolation:
<code phx-no-curly-interpolation>
let obj = {key: "val"}
</code>
Within phx-no-curly-interpolation annotated 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:
<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 ]):
<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:
<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:
<%!-- THIS IS INVALID NEVER EVER DO THIS --%>
<div id="<%= @invalid_interpolation %>">
{if @invalid_block_construct do}
{end}
</div>