Hi all,
I love surface and live_view! And I don’t love to write top level components with tailwind utility classes twice . So I wanted to use Surface to define a layout. Maybe I missed it out, but I always read, that there is not solution yet and I have to wait for surface component/3 to be released. But I didn’t want to.
I had the idea, that a live view is a view and a view could be a layout. I tried it with a surface live_view as layout and the TopNavigation
as a surface component:
defmodule Www do
...
def live_view do
quote do
use Surface.LiveView, layout: {Www.LiveLayout, "live.html"}
data top_menu_items, :list, default: []
unquote(view_helpers())
end
end
def component do
quote do
use Surface.Component
unquote(view_helpers())
end
end
...
@doc """
When used, dispatch to the appropriate controller/view/etc.
"""
defmacro __using__(which, opts \\ []) when is_atom(which) do
apply(__MODULE__, which, opts)
end
end
defmodule Www.LiveLayout do
use Www, :live_view
alias Www.Ui.TopNavigation
alias Surface.Components.LiveRedirect
def render("live.html", assigns), do: render(assigns)
def render(assigns) do
~F"""
<header>
<TopNavigation>
<:brand><LiveRedirect to={ Routes.page_path(@socket, :index) }>Experiment</LiveRedirect></:brand>
<:menu>
<TopNavigation.MenuItem :for={ {to, name} <- @top_menu_items } to={to}>{name}</TopNavigation.MenuItem>
</:menu>
</TopNavigation>
</header>
<TopNavigation.Content>
<main role="main" class="container">
<p class="alert alert-info" role="alert" phx-click="lv:clear-flash" phx-value-key="info">{live_flash(@flash, :info)}</p>
<p class="alert alert-danger" role="alert" phx-click="lv:clear-flash" phx-value-key="error">{live_flash(@flash, :error)}</p>
{@inner_content}
</main>
</TopNavigation.Content>
"""
end
end
And it works!
Besides of sharing the solution, I wrote this post to get the opinion of the community about:
Is it a hack or is it supposed to work like that?
- The fact, that I needed to write a render/2 function in the layout module makes it feel like a hack.
P.S. Later I needed the top_menu_items
as assigned values, so it clearly becomes a hack. Obviously mount is not called on the layout - but it still works , so this post is only for sharing a small war story.