Phoenix.HTML.Form pass custom assigns (key={value})

Suppose one defines a simple form like this:

<.simple_form :let={f} for={@changeset} focus={@focus}>

Then how would one collect the @focus value when defining an input:

<.input field={f[:name]} type="text" focus={@focus} />

Annotating simple_form/1 does not work.

attr :focus, :atom, default: nil
<.form :let={f} for={@for} as={@as} focus={@focus} {@rest}>

Phoenix.HTML.Form does not pass @focus or any custom value along.

Using @rest results in @focus being output as a form attribute.

So how does one trickle down key={value} ?

Many thanks.

You don’t need to pass the value to <.simple_form> in the first place. You can pass it to the input directly and that’s enough.

Thanks for your reply.

Suppose the initial value of @focus is a return value:

focus={get_focus(@changeset, [:field_b, :field_c, :field_a])}

A view implements get_focus/2 because the template knows the order of the fields to be rendered.

It seems like the key={value} syntax would be a nice (or logical?) way to make the @focus assign available downstream.

Where would you execute get_focus/2 and remember it’s return value?

The individual inputs are not “downstream” from <.simple_form>. The inner html is another input to <.simple_form>.

You don’t want to execute functions in templates if possible (when using LV), so rather calculate it in advance.

Thank you.

You would agree that <.celebrate name={"Genevieve"} age={34} /> makes @name and @age available “downstream”?
https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#module-attributes

With it we could do something like <.stuff name={@name} /> (or maybe <.input key={@value} />).

The function definition should allow for “passing down” such assigns.
So when a function does not allow custom attributes the key={value} thing does not work.
I guess Phoenix.HTML.Form would have to support customization.
Something like assign-focus="get_focus(@changeset, [:field_b, :field_c, :field_a])".

About calculating in advance.
That would mean the controller would have to know about the ordering of the inputs to be rendered.

It makes the values available to celebrate/1, yes.

<.celebrate name={"Genevieve"} age={34}>
  […]
</.celebrate>

Here anything being […] however is just another input to celebrate/1, similar to age and name. It won’t get access to any additional assigns. Using :let={…} is the only way for celebrate/1 to pass data back to its body/slots.

Thanks again.

So in conclusion as long as we are in control of a function we can define key={value} syntax.
When using form/1 or other functions out of our control we cannot use it.

Unless we do weird stuff like:

<.simple_form :let={f} for={@changeset} data-focus={get_focus(@changeset, [:field_b, :field_c, :field_a])}>

and

<input type={@type} autofocus={has_focus?(@__given__)}>

and

  def has_focus?(%{__given__: %{field: %{field: name, form: %{options: opts}}}}) do
    opts[:"data-focus"] == name
  end

  def has_focus?(_), do: false

and accept a data-focus attribute on our form.