We have a collection of about 50
live_components that we are migrating to function components (for most of them) and to HEEX templating.
Our components are used within different applications and can be themed according to application-level configuration. Our former
live_components used to fetch the theme according the application name defined in the
But function components no longer have access to the socket, and we don’t want to explicitly pass the theme as an assign in every template, we want something less obtrusive.
We already found a workaround when using new function components from LEEX templates: we wrote our own
component macro that un-hygienically injects the
theme in assigns.
We are wondering what would be the best unobtrusive way to inject theme when using function components in HEEX templates :
<.my_component_that_require_a_theme_assign ... />
Inject or wrap so you request the theme if it’s not assigned?
def render(assigns) do
assigns = assign_new(:theme, fn -> get_theme() end)
The issue is that the
get_theme function doesn’t have enough context to get the theme.
get_theme function take the
socket as a parameter (used to get the current phoenix application name, which is then used to fetch the proper application theme)
I finally managed to find a work-around: the theme is set at the router level using a
pre_mount hook in a
Registry. Using a
Registry makes the theme bound to a specific PID (liveview’s PID)
component that needs the theme can fetch it from the registry (since all components are running within the liveview’s process and hence share the same PID)
defmodule ThemeHook do
def on_mount(:default, _params, _session, socket) do
theme = socket |> app_name() |> ThemeHelpers.application_theme()
Registry.register(ThemeRegistry, :theme, theme)
used from the router
live_session :default, on_mount: ThemeHook do