Skip to content

Instantly share code, notes, and snippets.

@mcrumm

mcrumm/error.txt Secret

Last active April 26, 2021 22:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mcrumm/c11f2fb4dfa47dbf8fb5d9c93008a704 to your computer and use it in GitHub Desktop.
Save mcrumm/c11f2fb4dfa47dbf8fb5d9c93008a704 to your computer and use it in GitHub Desktop.
LiveView Form Auto Recovery
# Error occurred before I implemented the "recover" event handler in the LiveView.
[error] GenServer #PID<0.659.0> terminating
** (FunctionClauseError) no function clause matching in DropsWeb.FormsLive.Recovery.handle_event/3
(drops 0.1.0) lib/drops_web/live/forms_live/recovery.ex:47: DropsWeb.FormsLive.Recovery.handle_event("recover", %{"_csrf_token" => "JhlnPRYwFRQUPCBcAEEDFx4uFGkPDBVAOI4XDadyxmce5-QphAd-PEb6", "_target" => ["_csrf_token"], "foo" => %{"a" => "A", "b" => "B", "b_confirmation" => "B"}}, #Phoenix.LiveView.Socket<assigns: %{bar: %DropsWeb.FormsLive.Recovery.Bar{c: nil, d: nil, id: nil}, bar_changeset: #Ecto.Changeset<action: nil, changes: %{}, errors: [c: {"can't be blank", ...}], data: #DropsWeb.FormsLive.Recovery.Bar<>, valid?: false>, flash: %{}, foo: %DropsWeb.FormsLive.Recovery.Foo{a: nil, b: nil, b_confirmation: nil, ...}, foo_changeset: #Ecto.Changeset<action: nil, changes: %{}, ...>, live_action: :index}, changed: %{}, endpoint: DropsWeb.Endpoint, id: "phx-FnmEzEGkkrDsIBaF", parent_pid: nil, root_pid: #PID<0.659.0>, router: DropsWeb.Router, view: DropsWeb.FormsLive.Recovery, ...>)
(phoenix_live_view 0.15.5) lib/phoenix_live_view/channel.ex:342: anonymous fn/3 in Phoenix.LiveView.Channel.view_handle_event/3
(telemetry 0.4.3) /Code/mcrumm/live_upload_example/deps/telemetry/src/telemetry.erl:272: :telemetry.span/3
(phoenix_live_view 0.15.5) lib/phoenix_live_view/channel.ex:204: Phoenix.LiveView.Channel.handle_info/2
# Example output after reconnect
[info] CONNECTED TO Phoenix.LiveView.Socket in 39µs
Transport: :websocket
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "WGMUIx8iCFwcGQlvb0E-MxUrOCYVDzAi13GFMsy1pHJVZ-lTcDHbJFGT", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/css/app.css", "1" => "http://localhost:4000/js/app.js"}, "vsn" => "2.0.0"}
form recovery: %{
"_csrf_token" => "JjxqDx4fP11fBSpqYTY7HSI_A2kPHSQYOl9jLNN03TiSTZizTPs-PTSn",
"_target" => ["_csrf_token"],
"foo" => %{"a" => "AAA", "b" => "BBB", "b_confirmation" => "BBB"}
}
form recovery: %{"_target" => ["bar", "c"], "bar" => %{"c" => "CCC", "d" => "DDD"}}
defmodule DropsWeb.FormsLive.Recovery do
use DropsWeb, :live_view
alias DropsWeb.FormsLive.{Bar, Foo}
def mount(_, _, socket) do
foo = %Foo{}
bar = %Bar{}
{:ok,
socket
|> assign(:foo, foo)
|> assign(:foo_changeset, Foo.changeset(foo))
|> assign(:bar, bar)
|> assign(:bar_changeset, Bar.changeset(bar))}
end
def handle_event("validate", %{"_target" => ["foo" | _rest], "foo" => params}, socket) do
{:noreply,
update(socket, :foo_changeset, fn _ -> Foo.changeset(socket.assigns.foo, params) end)}
end
def handle_event("validate", %{"_target" => ["bar" | _rest], "bar" => params}, socket) do
{:noreply,
update(socket, :bar_changeset, fn _ -> Bar.changeset(socket.assigns.bar, params) end)}
end
def handle_event("recover", params, socket) do
IO.inspect(params, label: "form recovery")
{:noreply, socket}
end
end
<section class="row">
<section class="column">
<h2>Foo Form</h2>
<%= f = form_for @foo_changeset, "#", phx_change: "validate", phx_auto_recover: "recover" %>
<%= label(f, :a) %>
<%= text_input(f, :a) %>
<%= label(f, :b) %>
<%= text_input(f, :b) %>
<%= label(f, :b_confirmation) %>
<%= text_input(f, :b_confirmation) %>
</form>
</section>
<section class="column">
<h2>Bar Form</h2>
<%= f = form_for @bar_changeset, "#", phx_change: "validate", phx_auto_recover: "recover", csrf_token: false %>
<%= label(f, :c) %>
<%= text_input(f, :c) %>
<%= label(f, :d) %>
<%= text_input(f, :d) %>
</form>
</section>
</section>
defmodule DropsWeb.FormsLive.Foo do
use Ecto.Schema
embedded_schema do
field :a
field :b
field :b_confirmation
end
def changeset(struct, params \\ %{}) do
struct
|> Ecto.Changeset.cast(params, [:a, :b, :b_confirmation])
|> Ecto.Changeset.validate_required([:b, :b_confirmation])
end
end
defmodule DropsWeb.FormsLive.Bar do
use Ecto.Schema
embedded_schema do
field :c
field :d
end
def changeset(struct, params \\ %{}) do
struct
|> Ecto.Changeset.cast(params, [:c, :d])
|> Ecto.Changeset.validate_required(:c)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment