Skip to main content

Overview

A function component is any function that receives an assigns map as an argument and returns a rendered struct built with the ~H sigil.
def greet(assigns) do
  ~H"""
  <p>Hello, {@name}!</p>
  """
end
Function components are stateless and do not have a life-cycle, making them simpler than LiveComponents.

Macros

sigil_H/2

The ~H sigil for writing HEEx templates inside source files.
~H"""
<div title="My div" class={@class}>
  <p>Hello {@name}</p>
</div>
"""
HEEx is a HTML-aware and component-friendly extension of EEx that provides:
  • Built-in handling of HTML attributes
  • HTML-like notation for function components
  • Compile-time validation of template structure
  • Minimized data sent over the wire
  • Out-of-the-box code formatting via mix format

attr/3

Declares attributes for HEEx function components.
attr :name, :string, required: true
attr :age, :integer, default: 0

def celebrate(assigns) do
  ~H"""
  <p>Happy birthday {@name}! You are {@age} years old.</p>
  """
end
name
atom
The attribute name.
type
atom
The attribute type: :any, :string, :atom, :boolean, :integer, :float, :list, :map, :fun, {:fun, arity}, :global, or a struct module.
opts
keyword
default:"[]"
Options:
  • :required - Marks attribute as required
  • :default - Default value if not provided
  • :examples - Example values for documentation
  • :values - Exhaustive list of accepted values
  • :doc - Documentation string

slot/3

Declares a function component slot.
slot :header
slot :inner_block, required: true
slot :footer

def modal(assigns) do
  ~H"""
  <div class="modal">
    <div class="modal-header">{render_slot(@header) || "Modal"}</div>
    <div class="modal-body">{render_slot(@inner_block)}</div>
    <div class="modal-footer">{render_slot(@footer)}</div>
  </div>
  """
end
name
atom
The slot name (use :inner_block for the default slot).
opts
keyword
default:"[]"
Options:
  • :required - Marks slot as required
  • :validate_attrs - Validate slot attributes (default: true)
  • :doc - Documentation string
block
do block
default:"nil"
Code block containing attr/3 calls for slot attributes.
Named slot with attributes:
slot :column, doc: "Columns with labels" do
  attr :label, :string, required: true
end

attr :rows, :list, default: []

def table(assigns) do
  ~H"""
  <table>
    <tr>
      <th :for={col <- @column}>{col.label}</th>
    </tr>
    <tr :for={row <- @rows}>
      <td :for={col <- @column}>{render_slot(col, row)}</td>
    </tr>
  </table>
  """
end

embed_templates/2

Embeds external template files into the module as function components.
defmodule MyAppWeb.Components do
  use Phoenix.Component

  embed_templates "pages/*"
end
pattern
string
Wildcard pattern for files to embed.
opts
keyword
default:"[]"
Options:
  • :root - Root directory (default: __DIR__)
  • :suffix - String to append to function names

Functions

assign/3

Adds a key-value pair to assigns.
assign(assigns, :name, "Elixir")
assigns
map
The assigns map from a function component.
key
atom
The assign key.
value
any
The assign value.
return
map
Updated assigns map.

assign_new/3

Assigns a key with value from function if one does not yet exist.
assign_new(assigns, :bg_color, fn -> Enum.random(~w(red green blue)) end)
assigns
map
The assigns map.
key
atom
The assign key.
fun
function
Function returning the value (0 or 1 arity).

update/3

Updates an existing key with a function.
update(assigns, :count, &(&1 + 1))
assigns
map
The assigns map.
key
atom
The assign key to update.
fun
function
Function receiving current value (and optionally assigns) returning updated value.

changed?/2

Checks if the given key changed in assigns.
changed?(assigns, :count)
assigns
map
The assigns map.
key
atom
The assign key to check.
return
boolean
true if the key changed, false otherwise.

render_slot/2

Renders a slot entry with optional argument.
render_slot(@inner_block)
render_slot(@column, row)
slot
list | map
The slot to render.
argument
any
default:"nil"
Optional argument passed to the slot.
return
rendered | nil
Rendered slot content, or nil if slot has no entries.

to_form/2

Converts a data structure to a Phoenix.HTML.Form.
to_form(%{"email" => "[email protected]"})
to_form(changeset, action: :validate)
data
map | changeset | form
The source data for the form.
options
keyword
default:"[]"
Options:
  • :as - Name prefix for form inputs
  • :id - ID prefix for form inputs
  • :errors - Keyword list of errors
  • :action - Form action (:validate, :save, etc.)
return
Phoenix.HTML.Form.t()
Form struct for use in templates.

used_input?/1

Checks if the input field was used by the client.
used_input?(@form[:email])
field
Phoenix.HTML.FormField.t()
The form field to check.
return
boolean
true if field was focused, interacted with, or submitted.

live_render/3

Renders a LiveView within a template.
live_render(@conn, MyApp.ThermostatLive)
live_render(@socket, MyApp.ThermostatLive, id: "thermostat")
conn_or_socket
Plug.Conn.t() | Socket.t()
Connection or parent LiveView socket.
view
atom
The LiveView module to render.
opts
keyword
default:"[]"
Options:
  • :session - Extra session data
  • :container - Container tag and attributes
  • :id - Unique DOM and LiveView ID (required for child LiveViews)
  • :sticky - Maintain across live redirects

assigns_to_attributes/2

Filters assigns as a keyword list for use in dynamic tag attributes.
assigns_to_attributes(assigns, [:to, :new_window])
assigns
map
The assigns map.
exclude
list
default:"[]"
List of keys to exclude.
return
keyword
Filtered assigns as keyword list.

Built-in Components

live_component/1

Renders a Phoenix.LiveComponent within a parent LiveView.
<.live_component module={MyApp.WeatherComponent} id="thermostat" city="Kraków" />
module
atom
required
The LiveComponent module to render.
id
string
required
A unique identifier for the LiveComponent.
Any additional attributes are passed to the LiveComponent as assigns.

live_title/1

Renders a title with automatic prefix/suffix on @page_title updates.
<.live_title default="Welcome" prefix="MyApp · ">
  {assigns[:page_title]}
</.live_title>
prefix
string
default:"nil"
A prefix added before the content.
suffix
string
default:"nil"
A suffix added after the content.
default
string
default:"nil"
The default title to use if inner block is empty.

form/1

Renders a form.
<.form for={@form} id="my-form" phx-change="validate" phx-submit="save">
  <.input field={@form[:email]} />
</.form>
for
form | map | changeset
required
The form source data.
action
string
The action to submit the form to (required for non-LiveView forms).
as
atom
The prefix for input names and IDs.
csrf_token
any
CSRF token (auto-generated for POST actions).
method
string
The HTTP method (only used with :action).
multipart
boolean
default:"false"
Sets enctype to multipart/form-data for file uploads.

inputs_for/1

Renders nested form inputs for associations or embeds.
<.inputs_for :let={f_nested} field={@form[:emails]}>
  <.input type="text" field={f_nested[:email]} />
</.inputs_for>
field
Phoenix.HTML.FormField.t()
required
The form field for the association or embed.

Upload Components

upload_errors/1

Returns errors for the upload as a whole.
<div :for={err <- upload_errors(@uploads.avatar)}>
  {upload_error_to_string(err)}
</div>
upload
Phoenix.LiveView.UploadConfig.t()
The upload configuration.
return
list
List of error atoms (e.g., :too_many_files).

upload_errors/2

Returns errors for a specific upload entry.
<div :for={entry <- @uploads.avatar.entries}>
  <div :for={err <- upload_errors(@uploads.avatar, entry)}>
    {upload_error_to_string(err)}
  </div>
</div>
upload
Phoenix.LiveView.UploadConfig.t()
The upload configuration.
entry
Phoenix.LiveView.UploadEntry.t()
The upload entry.
return
list
List of error atoms (e.g., :too_large, :not_accepted).

Build docs developers (and LLMs) love