Rendering liveview inside another liveview with live_render generates a not_mounted_at_router error


full disclosure I am still very new to elixir and phoenix and liveview.

I am trying to transform a liveview controller and it’s. *.leex template into a component. The controller was auto generated with mix and I am trying to turn the :show controller into a re-usable component that can be embedded in other views.

The first of which was to insert it into page_live.html.leex which according to the docs should work when

<%# live_render(@socket, ChatDemo.ChatRoomLive.Show, id: "ChatWindow", session: %{"id" => "07593216-b033-40e1-8c03-f32aa7375dec"} ) %>

But I get a no match of right hand side value: :not_mounted_at_router and somehow the debug page doesn’t show the expected content for session. I know it does require an :id in the params.

the controller works as a standalone, but not when rendered in another *.leex, is it possible to write a mount function that will work with live_render ? What am I doing wrong? or miss understanding?

the router entry:

  scope "/", DemoWeb do
    pipe_through [:browser, :admin_view]
    live "/message/:id", MessageLive.Show, :show
    live "/message/:id/show/edit", MessageLive.Show, :edit

the liveview render call

<%= live_render(@socket, DemoWeb.ChatRoomLive.Show, id: "ChatWindow", session:  %{"id" => "07593216-b033-40e1-8c03-f32aa7375dec"} ) %>

the code seems to fail here

@impl true
  def mount(params, session, socket) do
    %{"id" => id} = params # FAILS HERE, but session only contains the csrf token
    if connected?(socket), do: Chat.subscribe()
    messages = Chat.list_message_for_chat_room(id)
    {:ok, socket
          |> assign(:messages, messages)
          |> assign(:message, %DemoWeb.Chat.Message{})

Which docs are you reading? From Phoenix.LiveComponent:

A component can be invoked as:

<%= live_component @socket, HeroComponent, content: @content %>

Yes, that was the page I was reading from… I managed to get further by commenting out my handle_params function. the logs had raised the issue it seems, but not the web based error.

Removing the handle_params fixed my issue. Also is @myself only possible to use in a live_component?

From Phoenix.LiveComponent - Targeting Component Events:

If you want to send the event to yourself, you can simply use the @myself assign, which is an internal unique reference to the component instance

Note @myself is not set for stateless components, as they cannot receive events.

So yes, @myself is specific to stateful components.

As for handle_params/3, this function is not for LiveComponents to handle events, it is for the parent LiveView to handle URL parameters. LiveComponent events are handled with handle_event/3 - either in the LiveView (if the component is stateless), or in the component itself (if the component is stateful AND the event has phx-target="<%= @myself %>")

Looking through the mount/3 function in the OP, I think there is also a lack of context here that might make it difficult to troubleshoot this issue. You’re talking about a LiveComponent, but mount/3 is the mount for LiveViews (components use mount/1). If you’re still having trouble, please share the full repository so we can see how the LC is interacting with the parent LV.