Hi,
I’m trying to create a Tab component with TabItem children using Surface. Currently it looks like this:
Tabs.ex
defmodule DoomWeb.Components.Tabs.Tabs do
use Surface.LiveComponent
prop(initial, :atom, required: true)
data(selected_tab, :atom, default: nil)
slot(tabs)
def mount(socket) do
{
:ok,
socket
|> assign(:selected_tab, :plans)
}
end
def handle_event(event, params, socket) do
case event do
n when n == "change_tab" ->
on_change_tab(params, socket)
_ ->
{
:noreply,
socket
}
end
end
defp on_change_tab(%{"tab" => tab_id}, socket) do
{
:noreply,
socket
|> assign(:selected_tab, String.to_atom(tab_id))
}
end
def render(assigns) do
~F"""
<div class="flex flex-wrap w-full">
<ul class="flex mb-0 list-none flex-wrap pb-0 flex-row border-b-1">
{#for tab <- @tabs}
<li
class="-mb-px mr-2 last:mr-0 flex-auto text-left"
:values={tab: tab.id}
:on-click="change_tab"
>
<a class="text-md font-bold px-0 rounded-t block leading-normal cursor-pointer text-skin-base">
{tab.title}
</a>
</li>
{/for}
</ul>
{#for tab <- @tabs}
<div class="block p-2 text-sm" :if={@selected_tab == tab.id}>
<#slot /> <-------- HERE how can i access tab item .slot??
</div>
{/for}
</div>
"""
end
end
TabItem.ex
defmodule DoomWeb.Components.Tabs.TabItem do
use Surface.Component, slot: "tabs"
prop(id, :atom, required: true)
prop(title, :string, required: true)
prop(icon, :string)
slot(default)
end
Then I can use it:
<Tabs id="subscription" initial={:plans}>
<TabItem id={:plans} title={gettext("Plans")}>
plans
</TabItem>
<TabItem id={:billing_history} title={gettext("Billing History")}>
billing history
</TabItem>
<TabItem id={:payment_method} title={gettext("Payment Method")}>
payment method
</TabItem>
</Tabs>
My question is how can I access inside the for expression
on the Tab.ex the slot of each of the TabItem, so that I can render them?