I’m trying to make a little library similar to how Phoenix.Flash works, but I can’t figure out how to make a default assign that gets carried over to LiveView.
I made a plug…
defmodule Web.LiveNotifyPlug do
import Plug.Conn
def init(opts \\ []), do: opts
def call(conn, _opts) do
assign(conn, :live_notify, nil)
end
end
But that assign is not available in any LV render function.
You must use assign_new/3 in a LiveView mount/3 callback to assign a value from the Plug pipeline:
defmodule Web.ExampleLive do
use Phoenix.LiveView
@impl Phoenix.LiveView
def mount(_params, _session, socket) do
{:ok, assign_new(socket, :live_notify, fn -> nil end)}
end
end
If the key already exists in the Plug.Conn assigns, it will be copied to the LiveView.Socket assigns. If it does not exist, then the function in the 3rd argument will be invoked to retrieve the value.
Note that this means the value from the Plug pipeline is only available during the initial static mount/render. Your library will need to provide another way for the LiveView to retrieve the value on a live mount/render, for instance with an on_mount/1 lifecycle hook:
defmodule Web.ExampleLive do
@moduledoc "Userland LiveView module"
use Phoenix.LiveView
on_mount LiveNotify
# or on_mount {LiveNotify, arg} if the user needs to supply data
# callbacks...
end
Your library defines an on_mount/4 function that will be invoked immediately before the LiveView mount callback:
defmodule LiveNotify do
@moduledoc "Library module"
# :default is the default argument if none was provided
def on_mount(:default, _params, _session, socket) do
{:cont, apply_live_notify(socket)}
end
def on_mount(_arg, _params, _session, socket) do
{:cont, apply_live_notify(socket)}
end
defp apply_live_notify(socket) do
assign_new(socket, :live_notify, fn -> nil end)
end
end