I have a sample LiveView app with 2 LiveViews and 1 LiveComponent. LiveView 1 is live_rendered from the app layout so that it appears on every page (kinda like a sidebar). LiveView 2 is displayed when the page is routed to. LiveView 2 has a LiveComponent embedded inside it. The LiveComponent has a phx-click-away
handle and a phx-target
of @myself
on it.
When my click is outside the LiveComponent but my click is inside LiveView 2, the click-away event fires, and the handle_event
is called. However when I click on LiveView 1, the browser console records the error: no component found matching phx-target of 1
, and the handle_event
for the click-away is never called. I am trying to understand the behavior of phx-click-away
, when it is inside a live-component, since this is unexpected. If the phx-click-away
were inside LiveView 2, then it would fire when I clicked on LiveView 1.
How can I replicate the same behaviour of phx-click-away
when it is fired on a LiveComponent, (especially when the LiveComponent is something like a dropdown that manages its own state, and needs phx-target={@myself}
)?
Here is some sample code to showing changes I made to reproduce this from the starter phoenix project.
router.ex:
... rest of router code
live "/", SecondLive
...
app.html.heex:
<main class="flex h-screen">
<%= live_render(@socket, ClickawayWeb.FirstLive, id: "first", sticky: true) %>
<.flash_group flash={@flash} />
<%= @inner_content %>
</main>
live/first_live.ex:
defmodule ClickawayWeb.FirstLive do
use ClickawayWeb, :live_view
@impl true
def mount(_params, _session, socket) do
{:ok, socket, layout: false}
end
@impl true
def render(assigns) do
~H"""
<div class="bg-blue-300 flex-1 p-4 h-full">
First (LiveView embedded in layout)
</div>
"""
end
end
live/second_live.ex:
defmodule ClickawayWeb.SecondLive do
use ClickawayWeb, :live_view
@impl true
def render(assigns) do
~H"""
<div class="bg-red-300 flex-1 p-4">
Second (LiveView on page) <.live_component module={ClickawayWeb.ThirdLive} id="third" />
</div>
"""
end
end
live/third_live.ex:
defmodule ClickawayWeb.ThirdLive do
use ClickawayWeb, :live_component
@impl true
def handle_event("clicked-away-third", _, socket) do
IO.inspect("clicked-away-third")
{:noreply, socket}
end
@impl true
def render(assigns) do
~H"""
<div class="bg-green-300 flex-1 p-4" phx-click-away="clicked-away-third" phx-target={@myself}>
Third (LiveComponent in second)
</div>
"""
end
end