In my phoenix app, I am trying to load a bunch of data and make them accessible to my root template (across all pages). To my knowledge, this is done via assigns, but I don't know where to load it.
I think something like
use App.LiveView
use App.News
assign(socket, news: News.all)
should work, but I don't know where to put this code, so the socket would be available. Coming from Express.js, I'm looking to do something like:
router.use((req, res, next) => {
// Load news into global variable
// ...
next()
})
Thanks for helping.
The non-LiveView Phoenix equivalent of Express' router.use
would be Router.plug/2
. You could just add a plug in a pipeline.
A plug could either be defined as a module or a simple function.
Here is a minimal example:
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
# ...
plug :my_plug # <= add your plug
end
def my_plug(conn, _opts) do
Plug.Conn.assign(conn, :news, News.all())
end
But this wouldn't work with LiveView, which doesn't have access to plug assigns. Since LiveView 0.17, you can use a mount hook to achieve this. You need to add an on_mount/1
to your AppWeb.live_view/0
.
def live_view do
quote do
use Phoenix.LiveView,
layout: {AppWeb.LayoutView, "live.html"}
on_mount AppWeb.NewsLiveFetcher # <= add this
unquote(view_helpers())
end
end
And implement AppWeb.NewsLiveFetcher
something like:
defmodule AppWeb.NewsLiveFetcher do
import Phoenix.LiveView
def on_mount(:default, _params, _session, socket) do
socket = assign_new(socket, :news, &News.all/0)
{:cont, socket}
end
end