defmodule Phoenix.LiveView.Controller do @moduledoc """ Helpers for rendering LiveViews from a controller. """ alias Phoenix.LiveView alias Phoenix.LiveView.Socket @doc """ Renders a live view from a Plug request and sends an HTML response from within a controller. It also automatically sets the `@live_module` assign with the value of the LiveView to be rendered. ## Options See `Phoenix.Component.live_render/3` for all supported options. ## Examples defmodule ThermostatController do use MyAppWeb, :controller # "use MyAppWeb, :controller" should import Phoenix.LiveView.Controller. # If it does not, you can either import it there or uncomment the line below: # import Phoenix.LiveView.Controller def show(conn, %{"id" => thermostat_id}) do live_render(conn, ThermostatLive, session: %{ "thermostat_id" => thermostat_id, "current_user_id" => get_session(conn, :user_id) }) end end """ def live_render(%Plug.Conn{} = conn, view, opts \\ []) do case LiveView.Static.render(conn, view, opts) do {:ok, content, socket_assigns} -> conn |> Plug.Conn.fetch_query_params() |> ensure_format() |> Phoenix.Controller.put_view(LiveView.Static) |> Phoenix.Controller.render( :template, Map.merge(socket_assigns, %{content: content, live_module: view}) ) {:stop, %Socket{redirected: {:redirect, %{status: status} = opts}} = socket} -> redirect_opts = Map.delete(opts, :status) |> Map.to_list() conn |> Plug.Conn.put_status(status) |> put_flash(LiveView.Utils.get_flash(socket)) |> Phoenix.Controller.redirect(redirect_opts) {:stop, %Socket{redirected: {:live, _, %{to: to}}} = socket} -> conn |> put_flash(LiveView.Utils.get_flash(socket)) |> Plug.Conn.put_private(:phoenix_live_redirect, true) |> Phoenix.Controller.redirect(to: to) end end defp ensure_format(conn) do if Phoenix.Controller.get_format(conn) do conn else Phoenix.Controller.put_format(conn, "html") end end defp put_flash(conn, nil), do: conn defp put_flash(conn, flash), do: Enum.reduce(flash, conn, fn {k, v}, acc -> Phoenix.Controller.put_flash(acc, k, v) end) end