nidu

nidu

Live view: passing form to nested live component breaks redirection

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 pass form: 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 from save 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?

Where Next?

Popular in Questions Top

dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: The documentation above suggests that while ...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127536 1222
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29703 241
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39523 209
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

We're in Beta

About us Mission Statement