Hello,
I’m trying to make a live view app with a form that has a nested live component.
page_live.ex -> form_component.ex -> nested_component.ex
(Repro repo is available here https://github.com/nidu/live-view-redirection-issue/tree/main/lib/test_web/live.)
In page_live:
<%= live_component TestWeb.FormComponent,
id: "test_form",
return_to: "/" %>
form_component:
defmodule TestWeb.FormComponent do
use TestWeb, :live_component
@impl true
def handle_event("save", _, socket) do
{:noreply,
socket
|> put_flash(:info, "Listing query updated successfully")
|> push_redirect(to: socket.assigns.return_to)}
end
@impl true
def render(assigns) do
~L"""
<%= f = form_for :model, "#",
id: "test_form",
phx_submit: "save",
phx_target: @myself %>
<div>Hello</div>
<div>
<%= live_component TestWeb.FormComponent.NestedComponent, %{form: f} %>
</div>
<button type="submit" phx-target="<%= @myself %>">Save</button>
</form>
"""
end
end
In nested_component:
defmodule TestWeb.FormComponent.NestedComponent do
use TestWeb, :live_component
@impl true
def update(%{form: form} = assigns, socket) do
{:ok,
socket
|> assign(assigns)}
end
@impl true
def render(assigns) do
~L"""
"""
end
end
When I press Save in the form - I get an error message like this:
[error] GenServer #PID<0.1118.0> terminating
** (RuntimeError) cannot redirect socket on update/2
(phoenix_live_view 0.15.7) lib/phoenix_live_view/utils.ex:413: Phoenix.LiveView.Utils.maybe_call_update!/3
(phoenix_live_view 0.15.7) lib/phoenix_live_view/diff.ex:327: Phoenix.LiveView.Diff.component_to_rendered/4
(phoenix_live_view 0.15.7) lib/phoenix_live_view/diff.ex:369: Phoenix.LiveView.Diff.traverse/6
(phoenix_live_view 0.15.7) lib/phoenix_live_view/diff.ex:430: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/6
(elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
(phoenix_live_view 0.15.7) lib/phoenix_live_view/diff.ex:342: Phoenix.LiveView.Diff.traverse/6
(phoenix_live_view 0.15.7) lib/phoenix_live_view/diff.ex:584: Phoenix.LiveView.Diff.render_component/9
(phoenix_live_view 0.15.7) lib/phoenix_live_view/diff.ex:197: Phoenix.LiveView.Diff.write_component/5
(phoenix_live_view 0.15.7) lib/phoenix_live_view/channel.ex:467: Phoenix.LiveView.Channel.component_handle_event/6
(stdlib 3.12) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib 3.12) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib 3.12) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{event: "event", join_ref: "4", payload: %{"cid" => 1, "event" => "save", "type" => "form", "value" => "_csrf_token=H2p3EEQ_Pm0LET0qez4EUyMvCH8ePhJCl2Ob1IO7cSrfM_O1ow1FIQq7"}, ref: "5", topic: "lv:phx-FpZOfwN3qcBKnAuH"}
State: %{components: {%{1 => {TestWeb.FormComponent, "test_form", %{flash: %{}, id: "test_form", myself: %Phoenix.LiveComponent.CID{cid: 1}, return_to: "/"}, %{changed: %{}, root_view: TestWeb.PageLive}, {318716392023482915064364044808860968093, %{1 => {110892913394776534321848086767214048172, %{}}}}}}, %{TestWeb.FormComponent => %{"test_form" => 1}}, 2}, join_ref: "4", serializer: Phoenix.Socket.V2.JSONSerializer, socket: #Phoenix.LiveView.Socket<assigns: %{flash: %{}, live_action: :index, query: "", results: %{}}, changed: %{}, endpoint: TestWeb.Endpoint, id: "phx-FpZOfwN3qcBKnAuH", parent_pid: nil, root_pid: #PID<0.1118.0>, router: TestWeb.Router, transport_pid: #PID<0.1115.0>, view: TestWeb.PageLive, ...>, topic: "lv:phx-FpZOfwN3qcBKnAuH", upload_names: %{}, upload_pids: %{}}
The way to get rid of this message:
- Don’t pass form to nested component (e.g. instead of
form: f
passform: 1
). I need to pass form, so that’s not an option. - Remove
update
method from nested component. This is a viable option but I’d still like to do something in my update - Remove
put_flash
fromsave
handler. This is an option but it’s still weird
I think it should work but for some reason it doesn’t and it somehow breaks when I pass the form that I need to pass. What’s the issue here?