sodapopcan
Dynamically render Surface components
Is there a nice way to dynamically render a Surface component? I actually don’t even really figure out a non-nice way atm.
I current have a main Page which contains the layout and I want to dynamically render content which would be components.
defmodule AppWeb do
use Surface.LiveView
data section, :string, default: "home"
def render(assigns) do
~H"""
<div>
<header><h1>header</h1></header>
<main>
<!-- Is it possible to render a component based on the `section` data attribute here? -->
</main>
</div>
"""
end
def handle_params(%{"section" => section}, _, socket} do
# Do some validation here to ensure `section` section is valid
{:noreply, assign(:section, section)}
end
end
Is there a better way of dong this? My first attempt involved having a Layout component with a slot, then each section is its own LiveView, but that felt a little heavy-handed. Each section is rich enough that I want them to be their own components, but not heavy enough that they warrant loading a new LiveView each time.
I feel like I’m missing something really obvious, but my focus is being pulled in all different directions in the past couple of weeks.
Thanks!
First Post!
sodapopcan
So, reading through the source of LiveDashboard I’ve come up with something.
Essentially:
defmodule AppWeb do
use Surface.LiveView
data page, :string
def render(assigns) do
~H"""
<div>
<header><h1>header</h1></header>
<main>
{{ @page.render(assigns) }}
</main>
</div>
"""
end
def handle_params(%{"page" => page}, _, socket} do
{:noreply, assign(:page, resolve_page(page))}
end
def handle_params(_, _, socket) do
{:noreply, assign(:page, AppWeb.Pages.Home)}
end
defp resolve_page("foo"), do: AppWeb.Pages.Foo
defp resolve_page("bar"), do: AppWeb.Pages.Bar
end







