Getting some weird error after generating codes using "mix.gen.live" commands more than once in an app

When generating codes using “mix.gen.live” more than once in the same app, there always is an error MAYBE generated by more than one “form_component.ex” modules which are using the same “core_component.ex”.

I am still confused whether it’s a bug in LiveView or that of my app.

** (KeyError) key :name not found in: %{__changed__: nil, __given__: %{__changed__: nil, field: %Phoenix.HTML.FormField{id: "demographic_gender", name: "demographic[gender]", errors: [], field: :gender, form: 

... omitted 

lib/market_web/components/core_components.ex:353: anonymous fn/2 in MarketWeb.CoreComponents."input (overridable 1)"/1 

--- omitted

Yesterday, I have spent eons of time to fix it, but in vain.

Thank you for reading, any comment shall be appreciated.

The CoreComponents are meant to be reused.
Most of the time I see an error like this is when I use a <.input ..> that has no name attribute.

Thank you for hint.
The error is clearly from the <.input …> field of FormComponent.ex, as commenting out those two <.input…> fields yields no error, but screen without input fields.

def render(assigns) do
    ~H"""
    <div>
      <.header>
        <%= @title %>
        <:subtitle>Use this form to manage demographic records in your database.</:subtitle>
      </.header>

      <.simple_form
        for={@form}
        id="demographic-form"
        phx-target={@myself}
        phx-change="validate"
        phx-submit="save"
      >
        <.input field={@form[:gender]} type="text" label="Gender" />
        <.input field={@form[:year_of_birth]} type="number" label="Year of birth" />
        <:actions>
          <.button phx-disable-with="Saving...">Save Demographic</.button>
        </:actions>
      </.simple_form>
    </div>
    """
  end

But, I can’t fix it.

Try with adding a :let={f} to the form and rewriting as field={f[:gender]}

Tried, but not working.

The render() function above was auto generated by “mix.gen.live”, so is expected to work as it is.

It seems a bug in the current LiveView 0.8.x.

Thank you ermanverschooten for help. :slightly_smiling_face:

Just wondering, do you have this in your core_components.ex?

  def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
    assigns
    |> assign(field: nil, id: assigns.id || field.id)
    |> assign(:errors, Enum.map(field.errors, &translate_error(&1)))
    |> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end)
    |> assign_new(:value, fn -> field.value end)
    |> input()
  end

Yes, there is, but slightly different version. I’m using {:phoenix_live_view, “~> 0.18.3”},

def input(%{field: {f, field}} = assigns) do
    assigns
    |> assign(field: nil)
    |> assign_new(:name, fn ->
      name = Phoenix.HTML.Form.input_name(f, field)
      if assigns.multiple, do: name <> "[]", else: name
    end)
    |> assign_new(:id, fn -> Phoenix.HTML.Form.input_id(f, field) end)
    |> assign_new(:value, fn -> Phoenix.HTML.Form.input_value(f, field) end)
    |> assign_new(:errors, fn -> translate_errors(f.errors || [], field) end)
    |> input()
  end

I have added your version too, but still not works. The error seems related to postgresql because sometimes the error message below shown when routing to a form_component.

[error] #PID<0.1420.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.1339.0>, stream id 3) terminated
Server: localhost:4000 (http)
Request: GET /demographics
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol Phoenix.Param not implemented for {"demographics-1", %Market.Survey.Demographic{__meta__: #Ecto.Schema.Metadata<:loaded, "demographics">, id: 1, gender: "prefer not to say", year_of_birth: 1989, user_id: 2, user: #Ecto.Association.NotLoaded<association :user is not loaded>, inserted_at: ~N[2023-04-12 13:10:21], updated_at: ~N[2023-04-12 13:10:21]}} of type Tuple. This protocol is implemented for the following type(s): Any, Atom, BitString, Float, Integer, Map
        (phoenix 1.7.2) lib/phoenix/param.ex:125: Phoenix.Param.Any.to_param/1
        (market 0.1.0) lib/market_web/components/core_components.ex:475: anonymous fn/4 in MarketWeb.CoreComponents."table (overridable 1)"/1
        (elixir 1.14.2) lib/enum.ex:4307: anonymous fn/3 in Enum.reduce/3
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/live_stream.ex:69: Enumerable.Phoenix.LiveView.LiveStream.do_reduce/3
        (elixir 1.14.2) lib/enum.ex:4307: Enum.reduce/3
        (market 0.1.0) lib/market_web/components/core_components.ex:474: anonymous fn/2 in MarketWeb.CoreComponents."table (overridable 1)"/1
        (market 0.1.0) /Users/x/market/lib/market_web/live/demographic_live/temp_auto_generated/index.html.heex:10: MarketWeb.DemographicLive.Index.render/1
        (elixir 1.14.2) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:396: Phoenix.LiveView.Diff.traverse/7
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:544: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7
        (elixir 1.14.2) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:396: Phoenix.LiveView.Diff.traverse/7
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:139: Phoenix.LiveView.Diff.render/3
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/static.ex:252: Phoenix.LiveView.Static.to_rendered_content_tag/4
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/static.ex:135: Phoenix.LiveView.Static.render/3
        (phoenix_live_view 0.18.18) lib/phoenix_live_view/controller.ex:39: Phoenix.LiveView.Controller.live_render/3
        (phoenix 1.7.2) lib/phoenix/router.ex:430: Phoenix.Router.__call__/5
        (market 0.1.0) lib/market_web/endpoint.ex:9: MarketWeb.Endpoint.plug_builder_call/2

After mix.ecto.reset, some part of the form_component works again as long as commentting out <.input …> fields in the form_component.

Hmm, yes I am at version 0.18.18. But it seems to me there is a discrepancy in the way the input component is called, the method you’re showing seems to expect field={f, :gender}, where f is the form, as set with a :let.
I would create a new phx project with the latest version and the same app name in a different folder and see what’s different. Just to save some time.

1 Like

Surely, I will try and leave the result here.