AE
Ash Elixirโ€ข3y ago
Jmanda

** (KeyError) key :options not found: Error on AshPhoenix.Form submit

This is my form
<.simple_form
for={@form}
id="todo-form"
phx-target={@myself}
phx-change="validate"
phx-submit="save"
>
<div class="row">
<div class="col col-sm-12 col-md-6">
<.input field={@form[:title]} type="text" label="Title" />
</div>
</div>

<:actions>
<.button phx-disable-with="Saving...">
<i class="fa-solid fa-floppy-disk mr-2"></i>Save Todo
</.button>
</:actions>
</.simple_form>
<.simple_form
for={@form}
id="todo-form"
phx-target={@myself}
phx-change="validate"
phx-submit="save"
>
<div class="row">
<div class="col col-sm-12 col-md-6">
<.input field={@form[:title]} type="text" label="Title" />
</div>
</div>

<:actions>
<.button phx-disable-with="Saving...">
<i class="fa-solid fa-floppy-disk mr-2"></i>Save Todo
</.button>
</:actions>
</.simple_form>
In my FormComponent:
impl true
def update(%{todo: todo} = assigns, socket) do
form =
if todo do
AshPhoenix.Form.for_action(todo, :update,
as: "todo",
api: MyApp.Todos
)
else
AshPhoenix.Form.for_action(MyApp.Todos.Todo, :create,
as: "todo",
api: MyApp.Todos
)
end

{:ok,
socket
|> assign(assigns)
|> assign(:form, form |> to_form())}
end
impl true
def update(%{todo: todo} = assigns, socket) do
form =
if todo do
AshPhoenix.Form.for_action(todo, :update,
as: "todo",
api: MyApp.Todos
)
else
AshPhoenix.Form.for_action(MyApp.Todos.Todo, :create,
as: "todo",
api: MyApp.Todos
)
end

{:ok,
socket
|> assign(assigns)
|> assign(:form, form |> to_form())}
end
The form is rendering and validations are working fine, however on submiting the form am getting KeyError:
[error] GenServer #PID<0.1208.0> terminating
** (KeyError) key :options not found in: #AshPhoenix.Form<resource: MyApp.Todos.Todo, action: :create, type: :create, params: %{"title" => "asdf"}, source: #Ash.Changeset<action_type: :create, action: :create ...
...
[error] GenServer #PID<0.1208.0> terminating
** (KeyError) key :options not found in: #AshPhoenix.Form<resource: MyApp.Todos.Todo, action: :create, type: :create, params: %{"title" => "asdf"}, source: #Ash.Changeset<action_type: :create, action: :create ...
...
If I change the form to use :let:
<.simple_form
:let={f}
for={@form}
id="todo-form"
phx-target={@myself}
phx-change="validate"
phx-submit="save"
....
<.simple_form
:let={f}
for={@form}
id="todo-form"
phx-target={@myself}
phx-change="validate"
phx-submit="save"
....
and change the input field:
<div class="col col-sm-12 col-md-6">
<.input field={{f, :title}} type="text" label="Name" />
</div>
<div class="col col-sm-12 col-md-6">
<.input field={{f, :title}} type="text" label="Name" />
</div>
I get the following error:
key :title not found in: %{__changed__: nil, __given__: %{__changed__: nil, field: {%Phoenix.HTML.Form{source: #AshPhoenix.Form<resource: MyApp.Todos.Todo, action: :create ........
key :title not found in: %{__changed__: nil, __given__: %{__changed__: nil, field: {%Phoenix.HTML.Form{source: #AshPhoenix.Form<resource: MyApp.Todos.Todo, action: :create ........
What could be the issue? Is there something am missing?
6 Replies
sevenseacat
sevenseacatโ€ข3y ago
can you post some of the backtrace so we can see what line the error is coming from?
Jmanda
JmandaOPโ€ข3y ago
Here is the stacktrace:
[error] GenServer #PID<0.1234.0> terminatingvehicle
** (KeyError) key :options not found in:

#AshPhoenix.Form<resource: MyApp.Todos.Todo, action: :create, type: :create, params: %{"name" => ""}, source: #Ash.Changeset<action_type: :create, action: :create, attributes: %{title: nil} ...
valid?: false, errors: true, submitted_once?: true, just_submitted?: true, ...>

(ash_phoenix 1.2.10) lib/ash_phoenix/form/form.ex:1438: AshPhoenix.Form.submit/2
(todo 0.1.0) lib/todo_web/live/todo_live/form_component.ex:87: MyAppWeb.TodoLive.FormComponent.save_todo/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:630: anonymous fn/4 in Phoenix.LiveView.Channel.inner_component_handle_event/4
(telemetry 1.2.1) my_app/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:207: Phoenix.LiveView.Diff.write_component/4
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:553: Phoenix.LiveView.Channel.component_handle_event/6
(stdlib 4.1.1) gen_server.erl:1123: :gen_server.try_dispatch/4
(stdlib 4.1.1) gen_server.erl:1200: :gen_server.handle_msg/6
(stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{topic: "lv:phx-F03OyPkC1xNe-wWF", event: "event", payload: %{"cid" => 3, "event" => "save", "type" => "form", "value" => "todo%5Bname%5D="}, ref: "8", join_ref: "4"}
[error] GenServer #PID<0.1234.0> terminatingvehicle
** (KeyError) key :options not found in:

#AshPhoenix.Form<resource: MyApp.Todos.Todo, action: :create, type: :create, params: %{"name" => ""}, source: #Ash.Changeset<action_type: :create, action: :create, attributes: %{title: nil} ...
valid?: false, errors: true, submitted_once?: true, just_submitted?: true, ...>

(ash_phoenix 1.2.10) lib/ash_phoenix/form/form.ex:1438: AshPhoenix.Form.submit/2
(todo 0.1.0) lib/todo_web/live/todo_live/form_component.ex:87: MyAppWeb.TodoLive.FormComponent.save_todo/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:630: anonymous fn/4 in Phoenix.LiveView.Channel.inner_component_handle_event/4
(telemetry 1.2.1) my_app/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:207: Phoenix.LiveView.Diff.write_component/4
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:553: Phoenix.LiveView.Channel.component_handle_event/6
(stdlib 4.1.1) gen_server.erl:1123: :gen_server.try_dispatch/4
(stdlib 4.1.1) gen_server.erl:1200: :gen_server.handle_msg/6
(stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{topic: "lv:phx-F03OyPkC1xNe-wWF", event: "event", payload: %{"cid" => 3, "event" => "save", "type" => "form", "value" => "todo%5Bname%5D="}, ref: "8", join_ref: "4"}
This is the code in handle event and on line 87 in my FormComponent:
def handle_event("save", %{"todo" => todo_params}, socket) do
save_todo(socket, socket.assigns.action, todo_params)
end
def handle_event("save", %{"todo" => todo_params}, socket) do
save_todo(socket, socket.assigns.action, todo_params)
end
defp save_todo(socket, :new, todo_params) do
IO.inspect(socket.assigns.form, label: "FORM")
case AshPhoenix.Form.submit(socket.assigns.form, params: todo_params) do
{:ok, todo} ->
notify_parent({:saved, todo})
......
end
defp save_todo(socket, :new, todo_params) do
IO.inspect(socket.assigns.form, label: "FORM")
case AshPhoenix.Form.submit(socket.assigns.form, params: todo_params) do
{:ok, todo} ->
notify_parent({:saved, todo})
......
end
ZachDaniel
ZachDanielโ€ข3y ago
yes, this is a bug actually
ZachDaniel
ZachDanielโ€ข3y ago
that should be referring to the options key from the form originally provided to that function This has been fixed in main, will release next week. Sorry about that ๐Ÿ™‚ We've had to do some adjusting to new patterns in phoenix 1.7.
Jmanda
JmandaOPโ€ข3y ago
Oh I see No worries I understand ๐Ÿ˜ , thanks for your feedback

Did you find this page helpful?