I feel like I’ve been spamming the forms of late as I try to upgrade an older LiveView project to Phoenix 1.16 and LV 0.17…
Anyway I have a component that renders a block:
@spec render(map()) :: LiveView.Rendered.t()
def render(assigns) do
~H"""
<.form let={f} for={@changeset} class="form" phx-change={"#{String.downcase(@type)}_change"} phx-submit={"#{String.downcase(@type)}_save"}>
<%= render_block(@inner_block, f: f) %>
</.form>
"""
end
The idea being that you can pass in a changeset and render the form fields as individual components. Like this:
<%=
live_component ProductInputComponent,
title: "Colors",
type: "Color",
entries: @colors,
changeset: @color_changeset do %>
<%= render_live_flash_messages @flash, key_prefix: :color_, close_event: "clear_flash" %>
<%=
live_component FormGroup.TextInputComponent,
f: @f,
field: :value,
label: "Color",
input_class: "form-control--select-height",
%>
<%=
live_component FormGroup.MultiplierInputComponent,
f: @f,
field: :price_multiplier,
label: "Price Multiplier",
step: 0.001,
%>
<% end %>
In this particular instance we are using the above template as a partial inside another form:
<%=
f =
form_for @changeset, "#",
id: "product_form",
phx_change: "product_change",
phx_submit: "product_save"
%>
...
<%= if "color" in @child_form_display do %>
<%= render "_add_color.html",
socket: @socket,
color_changeset: @color_changeset,
f: f %>
<% end %>
...
<% end %>
The parent form is for @changeset
and then we may also include a partial with the @color_changeset
. The ProductInputComponent
used to render a separate form for @color_changeset
, but now it seems like the @f
in the partial is referring to @changeset
and not @color_changeset
.
Previously the ProductInputComponent
generated inputs like this:
<input class="input-border form-control--select-height" id="product_color_value" name="product_color[value]" type="text">
Now it looks like this →
<input class="input-border form-control--select-height" id="product_form_value" name="product_form[value]" type="text">
The relevant change here is that the name (and ID) refers to the top level @changeset
and not @color_changeset
. Which means that when submitting data from the form everything is lumped into the product_form: %{}
params whereas previously the params looked like: %{product_form: %{}}, %{product_color: %{}}
It seems like render_block/2
isn’t passing the updated f
value back. I know this function is deprecated but from what I can tell it should still work- I think…
What am I missing?