I was wondering, imagine you have several (but not all) LiveViews where in the upon mount you would want to place some shared logic. For instance, you have an internal contract that every liveview will have a internal_id param on the session.
For now, in every LV I have code to fetch that value, transform it and put it on the socket assigns.
I was wondering if there would be a Plug-like alternative, where in the LV I could say
plug LiveViewHelpers.get_internal_id
Which would be called just prior to mount and update the assigns, to then call mount itself with the updated socket; kind of how plugs work in front of Phoenix controllers?
1 Like
The on_mount macro can do that and you can use live_session for sharing those across LV routes.
2 Likes
Thanks. I will look into that macro!
In router.ex
live_session :customer_portal,on_mount: [
{AmplifyWeb.UnifiedUserAuth, :require_authenticated},
] do
live "/portal/dashboard", CustomerPortalDashboard
end
In UnifiedUserAuth
def on_mount(:require_authenticated, _params, session, socket) do
socket = mount_current_scope(socket, session)
if socket.assigns.current_scope && socket.assigns.current_scope.unified_user do
{:cont, socket}
else
socket =
socket
|> Phoenix.LiveView.put_flash(:error, "You must log in to access this page.")
|> Phoenix.LiveView.redirect(to: ~p"/unified_users/log-in")
{:halt, socket}
end
end
2 Likes
Thanks both again for your suggestions. Unfortunately we are not using live_session our live routes as of today, all LiveViews are kicked of by live_render. So for now, duplicating the logic accross LVs will still be the way to go I guess.
You might be able to keep things as tidy as possible with the on_mount macro if you haven’t used it in your code already: Phoenix.LiveView — Phoenix LiveView v1.1.17
There’s even an example that “Ensures common assigns” that seems to fit your use case.
Edit: Oopsie daisy, I didn’t see that this was suggested above. It’s worth reiterating I don’t think you need to use live_session to use the on_mount macro.
That’s right. While the docs give an example using live_session that’s just one way to do it, and calling the macro directly is documented earlier within the macro docs:
def on_mount(:user, _params, _session, socket) do
{:cont, socket}
end
And then invoke it as:
on_mount {MyAppWeb.SomeHook, :user}
The “where to put the macro invocation” is mentioned in more detail elsewhere in the LiveView docs, refer to Security considerations — Phoenix LiveView v1.1.17
[…]
Now we can use the hook whenever relevant. One option is to specify the hook in your router under live_session:
live_session :default, on_mount: MyAppWeb.UserLiveAuth do
# Your routes
end
Alternatively, you can either specify the hook directly in the LiveView:
defmodule MyAppWeb.PageLive do
use MyAppWeb, :live_view
on_mount MyAppWeb.UserLiveAuth
...
end
If you prefer, you can add the hook to def live_view under MyAppWeb, to run it on all LiveViews by default:
Since you don’t use live_session, you can still use the other two ways.
2 Likes