F6 · the architecture · module 5
Templates, components & HEEx
F6.01 ended with a controller returning a response; HEEx is how that response becomes HTML.
HEEx — HTML+EEx, written in the ~H sigil or a
.html.heex file — is a template language that compiles to a structure the server
can render and, later, diff. A template is a pure function of its assigns: the controller sets
@courses from data the Catalog context exposed, and the
template renders it with :for, :if, and curly interpolation.
Repeated markup becomes a function component — a function from assigns to markup, declared
with attr and slot so its inputs are checked at compile time.
And a form is a changeset turned into a form, so the F6.03 validation surfaces as inline errors
and the submitted params flow back to the context. HEEx also escapes interpolated values by default, which closes
the most common injection hole without any ceremony.
Three dives: templates and the assigns they render, function components and slots, and changeset-backed forms — the view half of everything the controllers and contexts already built.
Assigns render into markup
@course = %{title: "Algebra", lessons: 6}
Change one assign and only the markup that reads it re-renders.
Three pieces of the view
The view layer is three things, and this module takes each in turn. A template renders the assigns a controller set. A component is reusable markup with a typed interface. A form is a changeset rendered for editing, with errors and a path back to the domain. Select a piece.
The view layer · select a piece
piece: Template
is: render the assigns
HEEx is not a string templating language with holes punched in it. It compiles to a structure that separates the static markup from the dynamic assigns, which is what lets the same templates power LiveView’s diffing in F6.06 without a rewrite.
Where the view sits
The view does not reach for data — it receives it. A controller (F6.01) calls the
Portal facade, gets back structs from a context (F6.04), and assigns them; the HEEx
template renders those assigns, composing function components as it goes; the result is HTML in the response.
Reading left to right, the only arrow into the template is assigns, never a query.
facade → assigns → HEEx → HTML
Keeping data access out of the template is the same discipline as the context boundary, one layer up: the controller fetches, the view renders. A query in a template couples markup to storage and defeats both.
Three deep dives
In order: templates and the assigns they render; function components and slots for reuse; and forms backed by changesets.
~H sigil, rendering @assigns with :for and :if, curly interpolation, and verified ~p routes.attr and slot, a reusable <.course_card>, and render_slot/1 for wrapping content.to_form/1 over a changeset, <.form> and <.input>, and F6.03 errors shown inline.F6.01 returned
a response — the controller’s last act was render/2 with assigns.
F6.05 renders it
HEEx turns those assigns into HTML, composing components and forms.
Start with templates and assigns, then function components and slots, then forms and inputs. This module follows F6.04 — contexts — and the next, F6.06, makes these same templates live with LiveView.
References
HEEx, function components, and forms in reference form.
Sources
- Phoenix — Phoenix.Component — the
~Hsigil,attr, andslot. - Phoenix — Components and HEEx — templates and function components in a Phoenix app.
- Phoenix — HTML.Form — the form data structure behind
<.form>. - Phoenix — Form bindings — forms, changesets, and inputs.