Hi everyone,
I’m currently working on a Phoenix LiveView project and I’ve encountered a challenge that I hope someone can help me with. I need to extend a lifecycle hook from the parent LiveViews to their child LiveComponents, but I’m struggling to find a clean and effective way to do this.
Context
I have several LiveViews and I want to attach a hook that should be executed for all handle_event
events, including those in child LiveComponents. Here’s a simplified version of my setup:
router.ex
...
live_session :name, on_mount: {MyApp.Live.Session, :default} do
live "/name", MyApp.Index, :index
end
...
live_auth.ex
defmodule MyApp.Live.LiveSession do
import Phoenix.Component
import Phoenix.LiveView
def on_mount(:default, _params, session, socket) do
login_time = session["login_time"]
if session_expired?(login_time) do
{:halt,
socket |> put_flash(:warn, "...") |> redirect(to: "/auth/oidc")}
else
{:cont,
socket
|> assign(:login_time, login_time)
|> attach_hook(:check_session, :handle_event, &check_session/3)}
end
end
defp check_session(event, _params, socket) do
login_time = socket.assigns.login_time
if session_expired?(login_time) do
{:halt,
socket |> put_flash(:warn, "...") |> redirect(to: "/auth/oidc")}
else
{:cont, socket}
end
end
defp session_expired?(login_time) do
if DateTime.diff(DateTime.utc_now(), login_time, :second) > 8 * 3600 do
true
else
false
end
end
end
The Problem
The hook works perfectly for events in the parent LiveView, but it doesn’t get triggered for events in the child LiveComponents. I want to ensure that the session check is performed for all events, including those in the LiveComponents.
Any guidance or examples on how to achieve this would be greatly appreciated. Thank you!