2

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.

Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
flaudre
  • 2,358
  • 1
  • 27
  • 45

1 Answers1

2

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
sabiwara
  • 2,775
  • 6
  • 11