Will LiveView slots support variable?

I was expecting the following to work, but f_terms is both unused and later undefined. It turns out because <:tab is a slot, it won’t close on variable. Would it be possible to support it / is that in the works?

        <.inputs_for :let={f_term} field={f[:terms]}>
          <:tab label="Terms">
            <.terms_form f={f_term} />
          </:tab>
        </.inputs_for>
2 Likes

I may be misremembering, but you can bind let directly in the slot, no? (On my phone, I can’t double check, sorry).

2 Likes

:let works by having render_slot(slot, …) pass in the value needed to render the slots’ contents. So the :let on the component tag likely only works for the @inner_block slot, as that’s where a render_slot(@inner_block, something) call would be providing a value for the variable.

On render_slot(@tab) there’s either nothing provided – so no data available when rendering tabs – or if data is provided (render_slot(@tab, something)) you’d need to put the :let in the slot tag: <:tab :let={f_term} …>.

There’s no magic sharing those values beyond what I just described.

For a mental model this pseudo code would be closer to how the underlying code works:

<.inputs_for field={f[:terms]}>
  <:tab label="Terms">
    <.terms_form f={f_term} />
  </:tab>
  <:inner_block :let={f_term}>
    …
  </:inner_block>
</.inputs_for>
3 Likes

@josevalim yes, named slots can receive via let, but that’s not what I was hoping to achieve here.

Thanks @LostKobrakai, this helps.

So I wanted there to be multiple slots named :tab, but my mental model is wrong and there would only be one, then…

1 Like

You can have many slots with the same name, that’s not a problem.

1 Like

Yes, you can have this:

<:tab label={"Example #{1}"}/>
<:tab label={"Example #{2}"}/>
<:tab label={"Example #{3}"}/>

But this is not supported:

<%= for i <- 1..3 do %>
  <:tab label={"Example #{i}"}/>
<% end %>

Since the inner_block might be rendered after the tabs are, this actually makes complete sense.

1 Like

<:tab :for={i <- 1..3}>…</:tab> works though. You just cannot wrap it in a block, because that’s hard for parsing.

1 Like

Oh, awesome, so I think this could actually work for me then:

<:tab :for={f_term <- form_for(f.source, f, :terms)} label="Terms">
  <.terms_form f={f_term} />
</:tab>

Thank you so much @LostKobrakai :heart: