Sebb
1
I want to build a custom select.
I need to render all options (when expanded) and always the selected option additionally at the top.
<.select>
<:opt label="label1">opt-inner-1</:opt>
<:opt label="label2" selected>opt-inner-2</:opt>
</.select>
will render like
selected: opt-inner-2
opt-inner-1
opt-inner-2
I want the options rendered in an extra component.
But I can’t just delegate the inner-block to the option
component.
I tried this:
def select(assigns) do
assigns = assign_new(assigns, :selected, fn -> Enum.find(assigns.opt, & &1[:selected]) end)
~H"""
<div>
<div>selected: <%= @selected.label %></div>
<%= for opt <- @opt do %>
<.option {opt} />
<% end %>
</div>
"""
end
def option(assigns) do
~H"""
<div style="padding: 1rem">
<div><%= @label %></div>
<div :if={@inner_block}>
(want to render inner block) <%!-- <%= render_slot(@inner_block) %> --%>
</div>
</div>
"""
end
You’re not providing @inner_block
to <.option />
:
<.option {opt}><%= render_slot(opt) %></.option>
1 Like
Sebb
3
thanks, this works. I thought I’d pass the inner_block, because opt
looks like this:
<%= for opt <- @opt do %>
<% dbg(opt) %>
opt #=> %{
__slot__: :opt,
inner_block: #Function<2.56207531/2 in Porter.nest/1>,
label: "label1"
}
But its not in the right form somehow.
I did have to make an adjustment though: The inner block in <.option />
will always be truthy now, even if its not set, so I have to do:
<.select>
<:opt label="label1">opt-inner-1</:opt>
<:opt label="label2" selected>opt-inner-2</:opt>
<:opt label="label3" />
</.select>
...
defmodule Components.Forms do
use Phoenix.Component
def select(assigns) do
assigns = assign_new(assigns, :selected, fn -> Enum.find(assigns.opt, & &1[:selected]) end)
~H"""
<div>
<div>selected: <%= @selected.label %></div>
<%= for opt <- @opt do %>
<.option {opt}>
<%= if opt.inner_block do %>
<%= render_slot(opt) %>
<% end %>
</.option>
<% end %>
</div>
"""
end
def option(assigns) do
~H"""
<div style="padding: 1rem">
<div><%= @label %></div>
<div>
<%= render_slot(@inner_block) %>
</div>
</div>
"""
end
end
LV doesn’t allow passing slots like that.
1 Like
Sebb
5
It’s amazing how flexible and easy this all is. LV is just a masterpiece.
1 Like