简体   繁体   中英

How to make a variable globally accessible across multiple templates

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM