#Liveview form from map

1 messages · Page 1 of 1 (latest)

tall dune
#

I feel like I'll never wrap my head around form handling stuff. I have this liveview where I'm trying to create a minimal form:

defmodule MatrixControllerWeb.Test2Live do
  use MatrixControllerWeb, :live_view

  require Logger

  @impl true
  def mount(_params, _session, socket) do
    options = %{
      0 => "Zero",
      1 => "One"
    }

    socket =
      socket
      |> assign(options: options)
      |> assign(form: to_form(%{"option" => 0}))

    {:ok, socket}
  end

  @impl true
  def render(assigns) do
    ~H"""
      <.form
        for={@form}
        phx-submit="connect">
      <br />

        <.input
        field={@form[:option]}
        type="select"
        options={@options} />

        <button>Submit</button>
      </.form>
    """
  end
end

Whenever I load the page the input component gives me an error saying "key :name not found in: (...assigns)". I can manually add all the keys that it complains about, but that seems to defeat the point. What am I missing?

oak latch
#

did you mess with your core_components.ex file or is it basically the same as when first generated? The .input component is defined in there, I'm not sure why it would be broken in this case, your code looks fine

#

I put your code into a freshly generated phoenix project and it works fine:

tall dune
#

It's a ~1 year old project that I'm coming back to, but AFAIK the core_components are untouched

oak latch
#

they might have been generated back when the field={...} attribute was a different shape, like I remember it used to be a tuple? I think something like field={{@form, :option}} maybe?

#

that doesn't looke right, and I can't remember the details, but I know for sure that it was definintely changed at one point

#

for reference, this is what a very recent core components input component looks like:

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

# other types here...

def input(%{type: "select"} = assigns) do
  ~H"""
  <div phx-feedback-for={@name}>
    <.label for={@id}><%= @label %></.label>
    <select
      id={@id}
      name={@name}
      class="mt-2 block w-full rounded-md border border-gray-300 bg-white shadow-sm focus:border-zinc-400 focus:ring-0 sm:text-sm"
      multiple={@multiple}
      {@rest}
    >
      <option :if={@prompt} value=""><%= @prompt %></option>
      <%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
    </select>
    <.error :for={msg <- @errors}><%= msg %></.error>
  </div>
  """
end
#

I'm betting yours looks very different

#

actually now that I think about it that change was from more than a year ago, so maybe not...